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.
});
});
我可以把这个傻瓜扔进我想要的任何地方,就行了。无需下载类,无需处理连接委托方法:只需几行即可轻松实现异步数据。这种方法与我之前的GCD方法之间的差异非常大,足以触发“真正的警报”。
因此,我的问题:使用NSData
+ GCD进行简单的数据下载任务而不是NSURLConnection
是否有任何警告(假设我不关心下载进度等事情)?
答案 0 :(得分:22)
你在这里失去了很多功能:
我想的可能还有更多。
正确的方法是创建一个类而不是管理下载。
例如,请参阅我自己的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);
}];
有关详细信息,请参阅github上的README file和示例项目。
这样:
答案 1 :(得分:12)
<强> WWDC 2010 Session Videos 强>
讲师说
“线程是邪恶的”。
对于网络编程,强烈建议在RunLoop中使用异步API。
因为,如果你使用NSData + GCD,如下所示,它每个连接使用一个线程。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
NSData* data = [NSData dataWithContentsOfURL:someURL];
它可能会使用许多连接和许多线程。使用GCD太容易了:-) 然后,许多线程为其堆栈占用了大量内存。 因此,你最好使用异步API,就像AliSoftware所说的那样。
答案 2 :(得分:2)
从OS X v10.9和iOS 7开始,首选方法是使用NSURLSession。它为您提供了一个漂亮的基于块的界面,以及取消,暂停和后台下载等功能。