我正在尝试创建一个类,该类将允许我从Web服务获取请求的数据。我被困在如何返回值上。
// FooClass.m
// DataGrabber is the class which is supposed to get values
dataGrabber = [[DataGrabber alloc] init];
xmlString = [dataGrabber getData:[NSDictionary dictionaryWithObjectsAndKeys:@"news", @"instruction", @"sport", @"section", nil]];
在此示例中,应该获取体育新闻。问题在于,DataGrabber异步获取数据,并最终从多个NSURLConnection委托方法中跳出。如何在FooClass中知道何时接收到数据?
最佳答案
与严格协议一起使用的委托模式对此非常有用(这是完成NSURLConnection时DataGrabber会发现的方式,对吗?)。我已经编写了许多使用这种方式使用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解析代码)。
我已经成功完成了很多次-另一个关键是,向用户提供页面正在加载的一些反馈是很好的-打开状态栏中的 Activity 指示器,向他们显示UIActivityIndicator等,然后当您的委托回调成功或失败返回时,您将摆脱它。
最后,我写了一个更详细的博客文章:Consuming Web APIs on the iPhone