我正在尝试创建一个类,该类将允许我从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 指示器,向他们显示UIActivityIndi​​cator等,然后当您的委托回调成功或失败返回时,您将摆脱它。

最后,我写了一个更详细的博客文章:Consuming Web APIs on the iPhone

08-05 21:57