问题描述
以下代码用于创建与远程服务器的通信会话并发送/接收 HTTP 请求/响应。
仅当在 NSURLSession 任务 (_dataTask) 超时后显式调用取消方法时,才会调用此回调。
注意,使用 tcpdump 可以很容易地观察到响应在客户端正确接收。
NSURLSessionConfiguration* config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 1;
NSURLSession* session = [NSURLSession sessionWithConfiguration:config delegate:nil delegateQueue:queue];
_dataTask = [session dataTaskWithRequest:req completionHandler:^(NSData * _Nullable data,NSURLResponse * _Nullable response,NSError * _Nullable error) {
if ([error code] == NSURLErrorCancelled) {
writeLog(LOG_ERROR,"NSURLErrorCancelled");
} else {
...
}
}];
[_dataTask resume]
// after timeout,the operation is cancelled.
sleep(100)
[_dataTask cancel];
我想知道使用 dataTask 是否有响应长度限制(因为它适用于响应正文中的小文件),如果有这样的限制,那么我应该使用哪种其他方法来克服它。
>我看到 NSUrlsession 中有一个专门用于下载文件的替代方法,称为 downloadTaskWithRequest,但它没有异步完成块。
谢谢!
解决方法
获取大资源时,应使用下载任务。数据任务将尝试在单个 datetime.date
对象中加载整个响应。同时在内存中加载大型资产不仅效率低下,而且如果它特别大,可能会导致问题。
下载任务非常适合这些任务,因为它会为您将资产流式传输到临时文件,从而减少峰值内存使用量。 (诚然,您可以使用委托模式手动实现与数据任务相同的功能,但下载任务会为您完成此操作。)
你说:
我看到 NSData
中有一个专门用于下载名为 NSURLSession
的文件的替代方法,但它没有异步完成块。
两个观察:
-
有一个演绎,
dataTaskWithRequest:completionHandler:
,它有一个完成块:downloadTaskWithRequest
请注意,如果您没有设置委托或以其他方式自定义您的
NSURLSession* session = [NSURLSession sharedSession]; NSURLSessionDownloadTask *task = [session downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable location,NSURLResponse * _Nullable response,NSError * _Nullable error) { ... }]; [task resume];
,我建议您使用sharedSession
。您不想不必要地实例化NSURLSession
对象。如果您确实必须实例化NSURLSession
,请将其重新用于后续任务和/或确保在提交该会话的最后一个任务后调用NSURLSession
,否则finishTasksAndInvalidate
将泄漏。而且,如果您实例化自己的NSURLSession
,则不必实例化自己的操作队列,因为如果您不提供操作队列,默认情况下它会为您创建一个串行队列。 -
不带块参数
downloadTaskWithURL:
的演绎也能工作。您需要做的就是为您的NSURLSession
指定一个delegate
,然后实现URLSession:downloadTask:didFinishDownloadingToURL:
。我建议这样做的原因是,通常,当我们下载非常大的资产(尤其是通过蜂窝网络)时,我们意识到用户可能想要离开我们的应用程序并让下载在后台完成。在这些情况下,我们会使用背景
NSURLSession
。并且在使用后台会话时,您必须使用这种基于委托的方法。因此,如果您认为最终可能会采用后台会话进行长时间下载,那么现在采用基于委托的方法并不是一个坏主意。有关详细信息,请参阅 Downloading Files in the Background。