【问题标题】:Asynchronous network operations in iOS 5iOS 5 中的异步网络操作
【发布时间】:2012-04-29 23:12:54
【问题描述】:

在我所见的任何地方,我都能看到人们明确地使用队列或运行循环来进行网络操作。我应该在 iOS 5 中仍然这样做,还是应该使用 NSURLConnection sendAsynchronousRequest:queue:completionHandler: 代替?这是在 iOS >= 5 中进行网络操作的首选方法吗?

【问题讨论】:

  • 如果您还不了解 AFNetworking,请查看它。

标签: objective-c ios networking ios5


【解决方案1】:

我无法回答别人的喜好,但我自己推出了

简而言之,这是对 NSURLConnection 接口的巨大改进,IMO。

【讨论】:

    【解决方案2】:

    这取决于。对于简单的事情,新的基于块的 API 让生活变得更轻松。但是,与实现 NSURLConnectionDelegate 方法相比,您会失去一些控制权。

    例如,无法取消已使用此方法启动的连接,或在下载所有数据之前处理响应(例如用于解析标头)。

    【讨论】:

    • 该方法也缺少进度通知,这对于大下载非常重要。
    【解决方案3】:

    您可以在 iOS 4 上执行类似的操作,也可以使用 GCD。

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
    
        NSData *data = [NSURLConnection sendSynchronousRequest:blah returningResponse:response error:blah];
        //process response body here
    
        dispatch_async(dispatch_get_main_queue(), ^{
    
            //Update UI Code here
            self.textView.text = [[NSString alloc] initWithData:data];
    
        });
    });
    

    此代码和 OP 发布的代码的问题在于,一旦建立连接,您就无法取消它们。 取消对 viewDidDisappear 的请求对提高应用程序的性能大有帮助。我在iOS PTL这本书上广泛讨论了这个问题

    您需要第三方网络框架(如 MKNetworkKit 或 RestKit 或现已失效的 ASIHTTP)的第二个原因是用于身份验证。大多数 Web 服务要求您使用 NSURLCredential(HTTP Basic 或 HTTP Digest 或 Windows NTLM 或 oAuth)进行身份验证

    如果您推出自己的代码,仅此一项就需要几天时间。并不是说你不应该这样做。但是没有必要,因为所有这些第三方框架都被广泛使用,与您自己的代码相比,它们中的机会、错误或性能问题更少。

    【讨论】:

    • 你不能取消发送给sendAsynchronousRequest:queue:completionHandler:NSOperationQueue 中的NSOperation 吗?
    • NSOperation 可以取消。但这不一定会取消操作。只有当您收到委托回调时,您才有机会取消它。例如,如果您的 NSURLConnection 下载了 100MB 的数据并且用户在中途取消了它,您可以取消它并在 didReceiveData: 委托回调中执行清理。如果不使用 NSURLConnection 委托,则无法取消操作(至少不会泄漏内存)。
    • 只是为了扩展这一点:取消NSOperation 实际上并没有停止它。它只是将其标记为“已取消”。由你的操作来处理这个事实。正如 Mugunth 所指出的,Cocoa 无法在任意操作启动后停止它。那会破坏内存管理。因此,除非您在操作中对isCanceled 实施各种检查,否则cancel 不会做太多事情。您不会免费取消。
    【解决方案4】:

    我写了一个blog post,比较了几种方法,包括NSURLConnectionAFNetworkingReactiveCocoa

    ReactiveCocoa 方法

    如果你想真正了解异步网络调用,你可以试试ReactiveCocoa。 ReactiveCocoa 允许您定义代表每个网络请求的信号。它允许你chain multiple dependent network calls

    #import <ReactiveCocoa/ReactiveCocoa.h>
    // ...
    
    -(RACSignal*)signalGetNetworkStep1 {
       NSURL* url = ...;
       return [RACSignal createSignal:^(RACDisposable *(id subscriber) {
          NSURLRequest *request1 = [NSURLRequest requestWithURL:url];
          AFJSONRequestOperation *operation1 = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
             [subscriber sendNext:JSON];
             [subscriber sendCompleted];
          } failure:^(AFHTTPRequestOperation *operation, NSError *error){
             [subscriber sendError:error];
          }];
          [operation1 start];
          return nil;
       }
    }
    
    -(void) yourMethod {
       [[self signalGetNetworkStep1] subscribeNext:^(id *x) {
          // perform your custom business logic
       }];
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多