【问题标题】:telling multiple events apart with NSURLConnection and asynchronous connections用 NSURLConnection 和异步连接区分多个事件
【发布时间】:2013-08-13 23:22:32
【问题描述】:

我正在编写一个 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 的特定数据)?

【问题讨论】:

    标签: ios http networking network-programming


    【解决方案1】:

    每个异步方法、函数或异步操作都有一种方法来“通知”客户端它已经完成。

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

    “调用站点”(在NSURLConnection 的情况下是委托实例)现在应该定义委托方法中接下来要做什么。

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

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

    那么,就和上面已经说的基本一样了:

    “调用站点”(即NSOperation 网络子类的客户端)现在应该定义完成处理程序中接下来要做什么。

    好吧,即使是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];
            }
       }];
    }
    

    【讨论】:

      猜你喜欢
      • 2012-11-25
      • 2010-09-24
      • 1970-01-01
      • 1970-01-01
      • 2011-12-20
      • 1970-01-01
      • 1970-01-01
      • 2012-09-19
      • 1970-01-01
      相关资源
      最近更新 更多