微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

NSURLSession:方法 dataTaskWithRequest 永远不会在冗长的响应中完成回调

如何解决NSURLSession:方法 dataTaskWithRequest 永远不会在冗长的响应中完成回调

以下代码用于创建与远程服务器的通信会话并发送/接收 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 的文件的替代方法,但它没有异步完成块。

两个观察:

  1. 有一个演绎,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,则不必实例化自己的操作队列,因为如果您不提供操作队列,默认情况下它会为您创建一个串行队列。

  2. 不带块参数 downloadTaskWithURL: 的演绎也能工作。您需要做的就是为您的 NSURLSession 指定一个 delegate,然后实现 URLSession:downloadTask:didFinishDownloadingToURL:

    我建议这样做的原因是,通常,当我们下载非常大的资产(尤其是通过蜂窝网络)时,我们意识到用户可能想要离开我们的应用程序并让下载在后台完成。在这些情况下,我们会使用背景 NSURLSession。并且在使用后台会话时,您必须使用这种基于委托的方法。因此,如果您认为最终可能会采用后台会话进行长时间下载,那么现在采用基于委托的方法并不是一个坏主意。

    有关详细信息,请参阅 Downloading Files in the Background

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?