The 委托模式与严格的协议一起使用对此非常有用(这就是 DataGrabber 如何发现 NSURLConnection 何时完成,对吧?)。我已经编写了许多以这种方式使用 XML 和 JSON 信息的 Web API。
// In my view controller
- (void) viewDidLoad
{
[super viewDidLoad];
DataGrabber *dataGrabber = [[DataGrabber alloc] init];
dataGrabber.delegate = self;
[dataGrabber getData:[NSDictionary dictionaryWithObjectsAndKeys:@"news", @"instruction", @"sport", @"section", nil]];
}
然后在您的 DataGrabber.h 文件中:
@protocol DataGrabberDelegate
@required
- (void) dataGrabberFinished:(DataGrabber*)dataGrabber;
- (void) dataGrabber:(DataGrabber*)dataGrabber failedWithError:(NSError*)error;
@end
在 DataGrabber.m 中:
- (void) getData:(NSDictionary*)dict
{
// ... Some code to process "dict" here and create an NSURLRequest ...
NSURLConnection *connection = [NSURLConnection connectionWithRequest:req delegate:self];
}
- (void) connectionDidFinishLoading:(NSURLConnection*)connection
{
// ... Do any processing with the returned data ...
// Tell our view controller we are done
[self.delegate dataGrabberFinished:self];
}
然后确保 Foo 实现了 DataGrabberDelegate 协议方法来处理每种情况。
最后,您的 DataGrabber 有一个delegate
属性(确保使用分配,而不是保留以避免保留循环):
@property (nonatomic, assign) id<DataGrabberDelegate> delegate;
当 NSURLConnection 异步加载在 DataGrabber 内部完成时,它们会按照上面列出的协议回调到您的 UIViewController,以便您可以更新 UI。如果这是一个请求,理论上您可以摆脱 DataGrabber 并将其放入视图控制器中,但我喜欢“分离我的关注点” - API 和视图控制器保持分离。它生成一个额外的层,但将“文本处理代码”保留在视图控制器之外(特别是 JSON 和 XML 解析代码)。
我已经成功地完成了很多次 - 另一个关键是向用户提供一些页面正在加载的反馈是很好的 - 打开状态栏中的活动指示器,向他们显示 UIActivityIndicator 等,然后当你的委托回调返回成功或失败时,你就可以摆脱它。
最后,我写了一篇关于此的更详细的博客文章:在 iPhone 上使用 Web API http://longweekendmobile.com/2010/10/15/how-to-consume-json-or-xml-web-apis-on-iphone-smoothly/