在Objective-C中,处理asynchronoushttp请求比委托更清晰吗?

我正在构build一个iPhone应用程序,大量利用我在PHP中编写的Web服务。 现在我有一个文件(API.h / API.m),它具有通过NSURLConnection在我的Web服务上调用PHP函数的方法。

方法如下:

-(void) mediaAdd:(UIImage *)image withDelegate: (id<apiRequest>) delegate; -(void) mediaGet:(NSString *)imageURL withDelegate: (id<apiRequest>) delegate; 

这些方法由应用程序中的控制器(由MVC模式定义的控制器)调用,并且方法以控制器作为委托。

一旦API.h / API.m中被调用方法的请求完成,请求完成时调用API.h / API.m中的NSURLConnection委托方法,然后调用委托方法…

 -(void) serverResponse:(NSDictionary *) response fromCall:(NSString *)call; 

…当然是在调用API.h / API.m中的方法的控制器上执行的。

当控制器需要进行多个API调用时,我的问题,或者更糟糕的情况就会出现。 因为我只有一个委托方法,所以我使用serverResponse方法中的call参数来区分不同的调用。

以下是serverResponse方法实例的一个框架:

 //API Delegate -(void)serverResponse:(NSDictionary *)response fromCall:(NSString *)call { bool local = false; NSString *callbackString; if (local) { callbackString = @"http://localhost/"; } else { callbackString = @"http://secret.com/"; } if ([call isEqualToString:[NSString stringWithFormat:@"%@user/add",callbackString]]) { //user/add was called if (![[response objectForKey:@"status"] isEqualToString:@"fail"]) { if ([[response objectForKey:@"status"] isEqualToString:@"fail"]) { if ([[response objectForKey:@"reason"] isEqualToString:@"udid already taken"]) { //UDID taken } } else { //UDID not taken, we're good to go } } else { NSLog(@"fail"); } } else if([call isEqualToString:[NSString stringWithFormat:@"%@moment/get",callbackString]]){ //moment/get was the api call } else if([call isEqualToString:[NSString stringWithFormat:@"%@printPictures/printPic",callbackString]]){ //printPictures/printPic was the api call } else { NSLog(@"wrong call"); } } 

我的问题是,我应该继续为每个API调用做一个委托方法吗? 或者我是否过度这个,实际上有一个非常简单的方法来处理这个问题。 也许是devise模式或结构?

谢谢! 迈克

我有一个单独的下载类与callback块做这种事情。 控制器创build类的一个实例,并在callback中接收结果,之后,下载类被释放。 您需要进行的每个调用都会创build自己的Downloader类的实例,因此您不需要跟踪哪个响应与哪个调用相关联。

  Downloader *dl = [Downloader new]; NSURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"...."]] cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:10]; [dl downloadWithRequest:(NSURLRequest *) request completion:^(NSData *data, NSError *error) { if (!error ) { // do whatever you need to do with the raw data here NSLog(@"got the data"); }else{ NSLog(@"%@",error); } }]; 

这是我如何实现Downloader类。

 typedef void(^compBlock)(NSData *data, NSError *error); @interface Downloader : NSObject <NSURLConnectionDataDelegate> -(void)downloadWithRequest:(NSURLRequest *) request completion:(compBlock) completion; @end 

执行文件,

 @interface Downloader() @property (copy,nonatomic) compBlock completionHandler; @property (strong,nonatomic) NSMutableData *receivedData; @end @implementation Downloader -(void)downloadWithRequest:(NSURLRequest *) request completion:(compBlock)completion { NSURLConnection *con = [NSURLConnection connectionWithRequest:request delegate:self]; if (con) { self.receivedData = [NSMutableData new]; self.completionHandler = completion; } } -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { self.receivedData.length = 0; } -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { [self.receivedData appendData:data]; } -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { self.completionHandler(nil, error); } -(void)connectionDidFinishLoading:(NSURLConnection *)connection { self.completionHandler(self.receivedData, nil); } 

当控制器需要进行多个API调用时,我的问题,或者更糟糕的情况就会出现。

对于这种事情,你应该看看NSURLSession和相关的类。 NSURLSession提供了像-sendAsynchronousRequest:queue:completionHandler:这样的方法,可以让你完成任务,而不必提供你自己的委托对象 – 会话将为你提供一个默认的委托,当任务完成时,默认的委托会调用你的完成处理器。

当然,您仍然可以select提供自己的委托,每个任务都有一个标识,以便您的委托可以跟踪NSURLConnection比哪个任务更容易。

我不会在这里介绍NSURLSession所有好处,因为你可以自己阅读它们 ,但是它们很重要。 如果你正在编写新的代码,你几乎肯定应该使用NSURLSession而不是NSURLConnection