这里的模式就像延迟加载图像。
1) 创建一个像 TrainStation 这样的自定义对象,它应该有一个 NSString 站代码、一些函数的 BOOL 属性,告诉调用者它是从 Web 服务初始化的,以及一个提供块完成处理程序的 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;
}