You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NSURLSession调用dataTaskWithRequest处理大响应无法触发完成回调问题

NSURLSessionDataTask响应长度说明

NSURLSessionDataTask 没有官方固定的响应长度限制,你遇到的大体积响应回调不触发问题,主要由两个原因导致:

  • dataTask的completionHandler机制默认会把所有响应数据全部加载到内存缓冲区,完整接收完成后才会触发回调。如果响应文件体积过大,超过当前App可用内存阈值,系统会中断数据缓冲流程,就会出现抓包已完整收数,但回调始终不触发的现象。
  • 你当前代码中[_dataTask resume]后直接执行sleep(100)会阻塞当前线程,如果你这段代码运行的线程恰好是你传入NSURLSession的代理队列对应的执行线程,就算数据已经接收完成,回调也无法被调度执行,只有cancel调用后才会触发取消对应的回调。

大体积响应的解决方案

首先纠正你的认知误区:downloadTaskWithRequest是支持异步完成回调的,iOS 7及以上系统就提供了带completionHandler的重载,它的工作机制是边接收数据边写入本地临时文件,不会占用大量内存,是大文件下载场景的最优选择。

方案1:使用带回调的downloadTask实现

NSURLSessionConfiguration* config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 1;

NSURLSession* session = [NSURLSession sessionWithConfiguration:config delegate:nil delegateQueue:queue];

NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:req completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    if (error) {
        if (error.code == NSURLErrorCancelled) {
            writeLog(LOG_ERROR, "NSURLErrorCancelled");
        }
        return;
    }
    // 临时文件会在回调结束后自动删除,需要移动到自定义沙箱路径持久化
    NSURL *saveDir = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask].firstObject;
    NSURL *savePath = [saveDir URLByAppendingPathComponent:response.suggestedFilename];
    NSError *moveError;
    [[NSFileManager defaultManager] moveItemAtURL:location toURL:savePath error:&moveError];
    if (!moveError) {
        // 下载完成,可从savePath读取文件
    }
}];
[downloadTask resume];

方案2:基于dataTask代理实现边收边存

如果必须使用dataTask,可以实现NSURLSessionDataDelegate相关代理方法,每收到一段数据就写入本地文件,不要全量缓存在内存:

  • 实现URLSession:dataTask:didReceiveData:代理,将收到的分片数据追加写入本地文件
  • 实现URLSession:task:didCompleteWithError:代理,处理下载完成或错误逻辑

内容的提问来源于stack exchange,提问作者Zohar81

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 02:42:04