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

iOS11新增NSURLSessionTask的progress属性为何失效?

iOS11中NSURLSessionTask.progress属性的坑与替代方案

哎,这个坑我当年在iOS11刚发布的时候可是踩得明明白白!你遇到的问题完全是系统这个新属性的设计缺陷导致的——iOS11给NSURLSessionTask加的progress属性,其实是统计整个任务的所有网络传输字节数,包括HTTP请求头、响应头,甚至重定向时的额外数据,而不是单纯的你要下载的文件内容大小。这就导致它的数值完全和实际下载进度对不上,比如你看到的78万字节下载了但进度显示0,就是因为系统把这些字节算成了“额外传输数据”,没算到下载内容的进度里;任务完成时的5字节更是离谱,大概率是最后收尾的一些响应数据被它当成了总进度。

那iOS11上要做可靠的UI进度展示,答案是肯定的:还是得自己写逻辑,别依赖系统的progress属性。最靠谱的方式还是用传统的下载代理方法来计算进度,这也是一直以来的稳定方案:

推荐实现方式

通过NSURLSessionDownloadDelegate的代理方法(如果是数据任务就用NSURLSessionDataDelegate的对应方法),直接拿到下载内容的真实字节数来计算:

Objective-C 示例

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
    // 排除未知总大小的情况
    if (totalBytesExpectedToWrite != NSURLSessionTransferSizeUnknown) {
        CGFloat progress = (CGFloat)totalBytesWritten / totalBytesExpectedToWrite;
        // 切回主线程更新UI
        dispatch_async(dispatch_get_main_queue(), ^{
            self.downloadProgressView.progress = progress;
        });
    }
}

Swift 示例

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
    guard totalBytesExpectedToWrite != NSURLSessionTransferSizeUnknown else { return }
    let progress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)
    // 主线程更新UI
    DispatchQueue.main.async {
        self.downloadProgressView.progress = progress
    }
}

为什么不推荐用系统的progress?

除了你遇到的数值混乱问题,iOS11的这个属性还有个坑:当任务遇到重定向或者服务器返回的Content-Length有变化时,progress的totalUnitCount会被重置,导致进度突然跳变或者归零,完全没法给用户展示稳定的进度。这个问题直到iOS12之后才得到部分修复,所以在iOS11上完全不能指望它。

总结一下:iOS11的NSURLSessionTask.progress就是个半成品,做UI进度展示还是老老实实用代理方法自己计算最稳妥,既能保证准确性,也不会出现莫名其妙的bug。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:02:00