iOS 8 - 在恢复任务之前由 NSURLSessionDownloadTask 创建的 fractionCompleted = 1.0 的 NSProgress 对象
Posted
技术标签:
【中文标题】iOS 8 - 在恢复任务之前由 NSURLSessionDownloadTask 创建的 fractionCompleted = 1.0 的 NSProgress 对象【英文标题】:iOS 8 - NSProgress object with fractionCompleted = 1.0 created by NSURLSessionDownloadTask before even resuming the task 【发布时间】:2014-09-11 12:09:09 【问题描述】:我有一个 NSProgress 对象树来监控涉及下载文件的数据处理。下载是使用带有后台配置的 NSURLSession 完成的。
当我开始这个过程时,最上面的 NSProgress 对象报告了意外的 fractionCompleted 数字。调试问题(并将其隔离到“Hello World”应用程序中), 我发现调用 [NSURLSession downloadTaskWithRequest:] 会创建一个 NSProgress 对象,并且在调用上述方法后它的 fractionCompleted 属性是 1.0。 由于这个 NSProgress 对象是我的 NSProgress 树的一部分,如果在树中偏移它上面的进度数字。
在这个示例应用程序中,我还启动了一个与下载并行的虚拟后台任务,它通过 NSProgress 对象报告进度。 我这样做的原因是,如果 NSURLSession 不创建任何 NSProgress 对象(这是 Apple 声称的),NSProgress 树中仍然至少有一个对象。
在启动下载后立即记录 NSProgress 树,这里的虚拟任务是 NSProgress 树的样子:
<NSProgress: 0x7ff8dae06b10> : Parent: 0x0 / Fraction completed: 0.5000 / Completed: 0 of 1
<_NSProgressGroup: 0x7ff8dae0f450> : Portion of parent: 1 Children: 1
<NSProgress: 0x7ff8dae0f880> : Parent: 0x7ff8dae06b10 / Fraction completed: 0.5000 / Completed: 0 of 100
<_NSProgressGroup: 0x7ff8dae0fec0> : Portion of parent: 100 Children: 2
<NSProgress: 0x7ff8dad74b90> : Parent: 0x7ff8dae0f880 / Fraction completed: 1.0000 / Completed: 1 of 1
<NSProgress: 0x7ff8daf036c0> : Parent: 0x7ff8dae0f880 / Fraction completed: 0.0000 / Completed: 0 of 100
因此,进度报告变得很奇怪。
如果我注释掉开始下载的调用 ([self resumeDownload]) 那么 NSProgress 树看起来像:
<NSProgress: 0x7febca52ac90> : Parent: 0x0 / Fraction completed: 0.0000 / Completed: 0 of 1
<_NSProgressGroup: 0x7febca529e60> : Portion of parent: 1 Children: 1
<NSProgress: 0x7febca529ff0> : Parent: 0x7febca52ac90 / Fraction completed: 0.0000 / Completed: 0 of 100
<_NSProgressGroup: 0x7febca52ced0> : Portion of parent: 100 Children: 1
<NSProgress: 0x7febca52d780> : Parent: 0x7febca529ff0 / Fraction completed: 0.0000 / Completed: 0 of 100
如您所见,没有额外的 NSProgress 对象,fractionCompleted = 1.0 并且进度报告正常。
现在,如果不是来自 NSURLSession 或下面的东西,我看不到带有 fractionCompleted = 1.0 的 NSProgress 来自哪里。 (Apple 声明 NSURLSession 不会创建 NSProgress 对象。) 我只能在 ios 8 上(即使是 GM 版本)在 iOS 7 上看到这种行为。
请注意,我正在使用带有后台配置的 NSURLSession!使用默认配置不存在此问题。
为什么“意外”的 NSProgress 对象会以 fractionCompleted = 1.0 出现? 我是否使用了 NSProgress API 错误? 是什么导致 iOS 7 和 8 上的行为截然不同?
示例代码在这里:https://s3-eu-west-1.amazonaws.com/pg.test/pubtest/NSProgress-20140830.zip
提前感谢您的帮助。
【问题讨论】:
【参考方案1】:我们在上传进度时遇到了同样的问题。正如您所说,创建任务的调用似乎正在创建一个 NSProgress 对象,该对象绑定到当前进度并立即完成。
uploadTask = [self.session uploadTaskWithRequest:request fromFile:fileURL];
这导致我们的整体进度出现问题。我们在我们的 AFNetworking 分支中创建了一个解决方法,以通过一个块创建 NSProgress 的回调。 AFURLSessionManager 中的方法已更新为具有进度创建块,而不是进度输出参数。
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request
fromFile:(NSURL *)fileURL
progress:(NSProgress *(^)(int64_t totalUnitCount))progressCreationBlock
completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
这确保只有在“进度”块中创建的进度对象作为直接子对象添加到当前进度,而不是创建会话的进度。来自被调用者的块的实现看起来像:
progress:^NSProgress *(int64_t totalUnitCount)
[currentProgress becomeCurrentWithPendingUnitCount:1];
NSProgress *progress = [NSProgress progressWithTotalUnitCount:totalUnitCount];
[currentProgress resignCurrent];
return progress;
https://github.com/cgreen-mmf/AFNetworking/commit/a0703a4f82a47e6c56c11245e4d88846ffbd0b28
我不清楚这是 iOS 8 中的错误还是预期的行为。
【讨论】:
以上是关于iOS 8 - 在恢复任务之前由 NSURLSessionDownloadTask 创建的 fractionCompleted = 1.0 的 NSProgress 对象的主要内容,如果未能解决你的问题,请参考以下文章
Linux内存从0到1学习笔记(8.9 可恢复硬件页面错误的含义)
Linux内存从0到1学习笔记(8.9 可恢复硬件页面错误的含义)