さてさて。

 最初にちょっと修正かまします。
 というのも、前回の表示をよくよくみるとハートの色がおかしいんですよ。

$テン*シー*シー-1

 元々のファイルが変なのかな~とimagesフォルダのぞいてみると、ちゃんとそれなりに並んでるんですな。

$テン*シー*シー-2
imagesフォルダの場所がわからん人は、その(229)を読みましょう

 じゃ、なんでと思ったけど、そもそもThumbnailViewAppDelegateの-imagesメソッドでファイルのリストアップさせた後、ファイル名で並び替えてませんでした。-contentsOfDirectoryAtPath:error:はファイル名の一覧は作るんですが、ファイル名順に並んでる保証はないんですな。
 もっとも、今回の場合
 test0.png
 test1.png
 test10.png
 test100.png
 test101.png
  ・
  ・
 test2.png
  ・
  ・
  ・

 て感じで並んでるっぽいけど、これはこれで具合悪い。
 という事で、-sortedArrayUsingComparator:使って並び替えます。
- (NSArray*)images
{
・・・
NSMutableArray* images = [NSMutableArray arrayWithCapacity:[names count]];
names = [names sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [obj1 compare:obj2 options:NSNumericSearch];
}];
for (NSString* name in names) {
[images addObject:[imageDirectory stringByAppendingPathComponent:name]];
}
return images;
}

 こいつは引数で受け取った並び替え用の比較処理のブロックオブジェクトを使って並び替えた結果を新しいNSArrayとして返すってメッセージです。
 ブロックオブジェクトはドリル本のQ13で簡単に説明したやつね。本持ってない人はApple提供の日本語ドキュメントの「Blocksプログラミングトピックス」を読みましょう。

 とりあえず
NSComparisonResult func(id obj1, id obj2) {…}

 というような関数の名前無し版(funcという部分が無くなってる)と思ってください。
 こいつがNSArrayの-sortedArrayUsingComparator:処理時に、obj1、obj2のどっちの格納オブジェクトが前になるかを決めるために何回か呼び出される事になります。

 NSArrayが格納しているファイル名をなんらかの規則に基づいて並び替える場合、格納しているオブジェクト(この場合ファイル名であるNSString)のどれが先頭で、どれが末尾かを決めるには、オブジェクト同士の比較が何回か必要なわけだけど、どっちが前か後ろかはNSArrayが決める事できないんで、-sortedArrayUsingComparator:を呼び出した側に問い合わせているわけですな。
 C言語で一般的な関数ポインタを使う-sortedArrayUsingFunction:context:なんてのもあるし、Objective-Cらしくセレクタを使った-sortedArrayUsingSelector:なんてものあるんですが、Appleはブロックオブジェクト一押しらしいので、私もそれに従います。
 じっさい便利だしね。

 で、中でやってるのはNSStringに装備されている-compare:options:での文字列オブジェクトの比較。options:にNSNumericSearchを指定する事で
 test0.png
 test1.png
 test10.png
 test100.png
 test101.png
  ・
  ・
 test2.png
  ・
  ・
  ・

 と並ばずに
 test0.png
 test1.png
 test2.png
 test3.png
  ・
  ・
 test10.png
 test11.png
  ・
  ・
 test99.png
 test100.png
 test101.png
  ・
  ・
  ・

 って並んでくれます。
 という感じで、これでやっと正しく並ぶわ~、やれやれだぜ~と実行してみると、一番最初のハートが無いんですな。

$テン*シー*シー-3

 こいつは、シミュレータ独自の問題といえるんですが、Mac上でフォルダ作ってファイル書き出すと
.DS_Store

 というファイルが作られるんですよ。こいつがリストに混じっちゃってたわけです。
 なので、ちょっと対策いれます。#ifdefでシミュレータ時のみってしてもよし。
- (NSArray*)images
{
・・・
for (NSString* name in names) {
if ([name isEqualToString:@".DS_Store"])
continue;

[images addObject:[imageDirectory stringByAppendingPathComponent:name]];
}
return images;
}

 あとその(230)でクラスの名称変更法紹介したけど、initWithNibName:の引数部分は直してくれないんで、自分で直さないと駄目です。
ThumbnailViewController* thumbnailViewController
= [[[ThumbnailViewController alloc] initWithNibName:@"ThumbnailViewViewController" bundle:nil] autorelease];

 を
ThumbnailViewController* thumbnailViewController
= [[[ThumbnailViewController alloc] initWithNibName:@"ThumbnailViewController" bundle:nil] autorelease];

 ね。文字列で指定するところなんでXcode側じゃ手が出せないわけね。すいま戦国自衛隊。

 とまあ、これでハートの並びは正しくなったので前回宣言した非同期処理いってみよー。

 まず、前回の-viewDidLoadの最後にThumbTileViewのloadingimagesというメソッドを非同期で実行するように-performSelectorInBackground:withObject:を_baseviewに送ります。
- (void)viewDidLoad
{
[super viewDidLoad];

// 先に画像用のベース作成、貼付け
_baseview = [[[ThumbTileView alloc] initWithFrame:self.view.bounds]autorelease];
[_baseview setImages:images thumbSize:CGSizeMake(100, 100)];
[self.view addSubview:_baseview];

// 画像読み込み処理非同期実行
[_baseview performSelectorInBackground:@selector(loadingimages) withObject:nil];

}

 こうすると-loadingimagesは、もともとの処理から別れ、それとは別に平行して動作する処理になるんですな。

$テン*シー*シー-4

 今まで利き腕だけで演奏してたのが、両手を使って演奏(もちろん別々の譜面を)するようになるわけですわ。
 つい、使い慣れてる非同期って書いてたけど、同時に別々に協調して動作(concurrent)と呼ぶのが適切ですね。
 元々の処理の流れをメインスレッド、分岐側をサブスレッドと言います。
 スレッドってのは糸って意味です。

 次に、ThumbTileView側に-loadingimagesメソッドを用意するわけですが、基本はThumbnailViewControllerで以前用意した-loadingimagesメソッドでやったように、全画像ファイルを読み込んでUIImageを作りUIImageViewに設定していくだけです。
 違うのはUIImageViewはすでに貼付け済みなので、作成せずに-viewWithTag:で検索する事、UIImageViewのimageプロパティにUIImageを設定する処理はメインスレッド側でおこなう事です。

 メインスレッドでおこなうためにやってるのが-performSelectorOnMainThread:withObject:waitUntilDone:というメッセージの自分への送信。
 これで-setimage:というメソッドがメインスレッド側で呼び出される事になる。
@implementation ThumbTileView
・・・
- (void)setimage:(id)dic
{
UIImage* image = [dic valueForKey:@"image"];
UIImageView* view = [dic valueForKey:@"view"];
view.image = image;
}

// 画像読み込み、貼付け処理
- (void)loadingimages
{
int tag = 1;
for (NSString* filepath in _images) {
UIImage* image = [UIImage imageWithContentsOfFile:filepath];
UIImageView* view = (UIImageView*)[self viewWithTag:tag++];
image = [self resizeImage:image size:view.bounds.size];
NSDictionary* dic = [NSDictionary dictionaryWithObjectsAndKeys:
image, @"image", view, @"view", nil];
[self performSelectorOnMainThread:@selector(setimage:)
withObject:dic waitUntilDone:NO];

}
}

 準備ができたら最後に-layoutSubviewsを消してからRunします。
 ハートは上から順に現れてきて、その間、スクロールもスムーズに動くはず。
 前々回、前回とは雲泥の操作感。ビバ、平行動作!

 ま、ちょっと解決しなけりゃいけない諸問題がいろいろ出るんですけどね。
 それは-performSelectorOnMainThread:withObject:waitUntilDone:メソッドの話も含め次回。

------------
サンプルプロジェクト:ThumbnailView-4.zip