使用NSURLConnection和异步连接分辨多个事件

时间:2013-08-13 23:22:32

标签: ios http networking network-programming

我正在编写一个iPad应用程序,它根据从服务器抓取的一些JSON数据填充UI。我正在使用NSURLConnection进行初始连接:

// Create the request.
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://foo.com/login"]];
[request setHTTPMethod:@"POST"];

NSString* credentials = @"username=testFoo&password=passFoo";

self.fFooConnectionData = [credentials dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:self.fFooConnectionData];

self.fFooDataConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[self.fFooDataConnection start];

现在,我的问题是我可以在'connectionDidX'委托函数中捕获响应,但是对于后续步骤,我该如何处理?如果这是同步连接,问题会更容易,我只是等待返回值,但是使用异步连接,我将如何处理后续请求?如何告诉另一个事件(如登录)(如请求UI的特定数据)?

1 个答案:

答案 0 :(得分:0)

每个异步方法,函数或异步操作都有一种方法“向客户端发出信号”它已经完成。

NSURLConnection使用委托方法向委托发出“事件”信号。委托方法connectionDidFinishLoading:分别connection:didFailWithError:表示数据最终被下载,分别表示发生了错误。

“调用站点”(即NSURLConnection的情况下的委托实例)现在应该在委托方法中定义下一步

您只需要确保 next 操作的“执行上下文”是合适的:例如,在NSURConnection的某个设置中,可以在私人辅助线程。假设客户希望使用下载的数据并将其显示在表格视图中。 UIKit方法只能在主线程上调用。因此,需要确保通过,例如,将操作分派到适当的队列,即主队列。

异步处理更复杂的NSURLConnection任务,发出异步事件信号的委托方法变得非常笨拙。更好的方法是对网络任务使用异步操作。您可以将NSURLConnection任务“包装”到NSOperation的子类中以实现该专用目的。你得到的是一个可能复杂的类,它在内部处理所有复杂性并提供了一个易于使用的API。客户端需要指定“完成处理程序”(块)而不是处理委托方法。这极大地减少了对象之间的依赖关系,极大地简化了编码任务。

然后,它与上面已经说的基本相同:

“呼叫站点”(即NSOperation网络子类的客户端)现在应该在完成处理程序中定义下一步要执行的操作。< / p>

好吧,即使是NSOperation子类也可能变得笨拙,特别是如果您必须为请求设置许多参数并执行所有令人讨厌且精心设计的错误处理。您偶尔想要的是一种更简单的调用方式。所以,你可以定义一个非常特殊的“方法”,比如说,

-(void) fetchMessagesWithUser:(User*)user completion:(completion_t)completionHandler;

在内部,您可以根据NSOperation的子类实现该方法,NSURLConnection本身是在- (void) fetchUserMessages { [self fetchMessagesWithUser:self.currentUser completion:^(id result){ // result is an NSData containing JSON (array of messages for a user) or an NSError if (![result isKindOfClass:[NSError class]]) { NSArray* messages = ... // invoke JSON parser dispatch_async(dispatch_get_main_queue(), ^{ [self updateViewWithMessages:messages]; }); } else { [self handleError:result]; } }]; } 之上实现的。你把所有讨厌的锅炉板放进去,包括大量的错误检查。

然后,您的代码变得更加“干净”:

{{1}}