NSURLConnection与NSData + GCD

Mat*_*ing 29 objective-c nsurlconnection grand-central-dispatch ios

NSData一直有一个非常方便的方法叫做+dataWithContentsOfURL:options:error:.虽然方便,但它也会阻止当前线程的执行,这意味着它对生产代码(忽略NSOperation)基本上没用.我很少使用这种方法,我完全忘记了它的存在.直到最近.

我从管中获取数据的方式是标准NSURLConnectionDelegate方法:编写一个处理各种NSURLConnectionDelegate方法的下载类,逐步构建一些数据,处理错误等.我通常会使这个通用的足以重用为尽可能多的要求.

假设我的典型下载程序类在100行的球场中运行.这是100行异步做什么NSData可以在一行同步.为了更复杂,下载程序类需要自己的委托协议来向其所有者传达完成和错误,并且所有者需要以某种方式实现该协议.

现在,进入Grand Central Dispatch,我可以做一些非常简单的事情:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {

    NSData* data = [NSData dataWithContentsOfURL:someURL];
    // Process data, also async...

    dispatch_async(dispatch_get_main_queue(), ^(void) {
        // Back to the main thread for UI updates, etc.
    });
});
Run Code Online (Sandbox Code Playgroud)

而且我可以把这个傻瓜扔进我想要的任何地方,就像在线一样.无需下载类,无需处理连接委托方法:只需几行即可轻松实现异步数据.这种方法与我之前的GCD方法之间的差异非常大,足以触发太好的真实警报.

因此,我的问题:使用NSData+ GCD进行简单的数据下载任务是否有任何警告而不是NSURLConnection(假设我不关心下载进度之类的事情)?

Ali*_*are 22

你在这里失去了很多功能:

  • 无法遵循下载进度
  • 无法取消下载
  • 无法管理可能的身份验证过程
  • 您无法轻松处理错误,这在iPhone上的移动开发中非常重要(当然,因为您经常在实际条件下丢失网络,因此在开发iOS时跟踪此类网络错误情况非常重要)

而且我猜可能还有更多.


正确的方法是创建一个类而不是管理下载.

OHURLLoader例如,请参阅我自己的类,这很简单,我使API易于使用块:

NSURL* url = ...
NSURLRequest* req = [NSURLRequest requestWithURL:url];

OHURLLoader* loader = [OHURLLoader URLLoaderWithRequest:req];
[loader startRequestWithCompletion:^(NSData* receivedData, NSInteger httpStatusCode) {
    NSLog(@"Download of %@ done (statusCode:%d)",url,httpStatusCode);
    if (httpStatusCode == 200) {
        NSLog(%@"Received string: %@", loader.receivedString); // receivedString is a commodity getter that interpret receivedData using the TextEncoding specified in the HTTP response
    } else {
        NSLog(@"HTTP Status code: %d",httpStatusCode); // Log unexpected status code
    }
} errorHandler:^(NSError *error) {
    NSLog(@"Error while downloading %@: %@",url,error);
}];
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅github上的README文件和示例项目.

这条路:

  • 你仍然依赖NSURLConnection提供的异步方法(正如Apple的文档中提到的并发编程一样,如果API已经存在以进行异步任务,请使用它而不是依赖于另一种线程技术,如果可能的话)
  • 你保持NSURLConnection的优势(错误处理等)
  • 但是你也拥有块语法的优点,使你的代码比使用委托方法时更具可读性

  • 谢谢!请注意,自从我写了这个答案以来,Apple已经向`NSURLConnection`添加了一个新方法(自iOS5以来可用),使用块执行异步请求(因此我不再需要旧的`OHURLLoader`).有关详细信息,请参阅文档中的`+ [NSURLConnection sendAsynchronousRequest:queue:completionHandler:]`. (3认同)

Kaz*_*oto 12

WWDC 2010会议视频:

  • WWDC 2010 Session 207 - 适用于iPhone OS的网络应用程序,第1部分
  • WWDC 2010 Session 208 - 适用于iPhone OS的网络应用,第2部分

讲师说

"线程是邪恶的".

对于网络编程,强烈建议在RunLoop中使用异步API.

因为,如果您使用NSData + GCD,如下所示,它每个连接使用一个线程.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
    NSData* data = [NSData dataWithContentsOfURL:someURL];
Run Code Online (Sandbox Code Playgroud)

它可能会使用许多连接和许多线程.使用GCD太容易了:-)然后,许多线程为其堆栈占用了大量内存.因此,你最好使用异步API,如AliSoftware所说.