objective-c - NSURLConnection 与 NSData + GCD

标签 objective-c ios nsurlconnection grand-central-dispatch

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

我从管道中获取数据的方式是标准的 NSURLConnectionDelegate 方法:编写一个处理各种 NSURLConnectionDelegate 方法的下载类,逐渐建立一些数据,处理错误等。我通常会使其足够通用,以便尽可能多地重复使用请求。

假设我的典型下载程序类运行在 100 行左右的某个地方。这是 100 行异步执行 NSData 可以在一行中同步执行的操作。对于更复杂的情况,该下载器类需要一个自己的委托(delegate)协议(protocol)来将完成和错误传达给它的所有者,并且所有者需要以某种方式实现该协议(protocol)。

现在,进入 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.
    });
});

而且我可以把那个傻瓜扔到任何我想要的地方,就在直线上。无需下载类,无需处理连接委托(delegate)方法:只需几行即可轻松处理异步数据。这种方法与我的 GCD 之前的方法之间的差异大到足以触发“好得不像真的”警报。

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

最佳答案

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

  • 无法跟上下载进度
  • 无法取消下载
  • 无法管理可能的身份验证过程
  • 您不能轻易处理错误,这非常重要当然尤其是在 iPhone 等移动开发中(因为您经常在真实情况下失去网络,因此跟踪此类问题非常重要为 iOS 开发时的网络错误案例)

我想可能还有更多。


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

看我自己的OHURLLoader例如类,它很简单,我使 API 易于与 block 一起使用:

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);
}];

查看 README file和 github 上的示例项目以获取更多信息。

这样:

  • 您仍然依赖 NSURLConnection 提供的异步方法(和 as the Apple's documentation says about Concurrency Programming 如果已经存在一个 API 来执行异步任务,请尽可能使用它而不是依赖其他线程技术)
  • 你保留了 NSURLConnection 的优势(错误处理等)
  • 但是您还拥有 block 语法的优势,它使您的代码比使用委托(delegate)方法时更具可读性

关于objective-c - NSURLConnection 与 NSData + GCD,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7421808/

相关文章:

iOS - API 对象和 Controller 之间的通信

ios - 使用 "Pause"和 "Resume"功能从服务器下载数据

objective-c - 除了 Xcode,是否有针对 Objective-C 的全功能 IDE?

iphone - 使用 UI Web View 下载文件

objective-c - 在 NSView 中加载 SWF

ios - 使用选项卡 View Controller 的演练

iphone - 在 ABPeoplePickerNavigationController 中更改 UISearchBar 的 tintColor

iphone - Xcode 在静态单元格上设置附件标记错误

ios - 如何在使用物理时在 SceneKit 中移动子节点及其父节点?

ios - 从缓存响应中停止 NSURLConnection sendAsynchronousRequest