ここでのパターンは、画像の遅延読み込みのようなものです。
1) TrainStation のようなカスタム オブジェクトを作成します。これには、NSString 駅コード、呼び出し元に Web サービスから初期化されたことを伝える関数の BOOL プロパティ、およびブロック完了ハンドラーを提供する init メソッドが必要です。
// TrainStation.h
@interface TrainStation : NSObject
@property (strong, nonatomic) NSString *stationCode; // your two character codes
@property (strong, nonatomic) id stationInfo; // stuff you get from the web service
@property (strong, nonatomic) BOOL hasBeenUpdated;
@property (copy, nonatomic) void (^completion)(BOOL);
- (void)updateWithCompletion:(void (^)(BOOL))completion;
@end
2) 完了ハンドラーは NSURLConnection を開始し、後で解析が完了したときに完了ブロックを保存します...
// TrainStation.m
- (void)updateWithCompletion:(void (^)(BOOL))completion {
self.completion = completion;
NSURL *url = // form this url using self.stationCode
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
[NSURLConnection sendAsynchronousRequest:self queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
}];
}
// TrainStation does it's own parsing, then
- (void)parserDidEndDocument:(NSXMLParser *)parser
self.hasBeenUpdated = YES;
self.completion(YES);
// when you hold a block, nil it when you're through with it
self.completion = nil;
}
3) テーブルを含むビュー コントローラーは、スクロールに応じてテーブルビュー セルが好きなように行き来することを認識する必要があるため、Web 結果の唯一の安全な場所はモデル (TrainStations の配列) です。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// normal stuff, dequeue cell, etc.
// the interesting part
TrainStation *trainStation = self.array[indexPath.row];
if ([trainStation hasBeenUpdated]) {
cell.detailTextLabel.text = [trainStation.stationInfo description];
// that's just a shortcut. teach your train station how to produce text about itself
} else { // we don't have station info yet, but we need to return from this method right away
cell.detailTextLabel.text = @"";
[trainStation updateWithCompletion:^(id parse, NSError *) {
// this runs later, after the update is finished. the block retains the indexPath from the original call
if ([[tableView indexPathsForVisibleRows] containsObject:indexPath]) {
// this method will run again, but now trigger the hasBeenUpdated branch of the conditional
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation: UITableViewRowAnimationAutomatic];
}
}];
}
return cell;
}