我有一个NSProgress对象树来监视涉及下载文件的数据处理。下载使用后台配置的NSURLSession完成。
当我开始这个过程时,最上面的NSProgress对象报告了意外的fractionCompleted数字。调试了这个问题(并将其隔离到一个"Hello World“应用程序中)后,我发现调用NSURLSession downloadTaskWithRequest:后创建了一个NSProgress对象,并且在调用上面的方法之后,它的fractionCompleted属性为1.0。因为这个NSProgress对象获取我的NSProgress树的一部分,所以如果偏移树中它上面的进度数字。
在这个示例应用程序中,我还启动了一个与下载并行的虚拟后台任务,该任务通过一个NSProgress对象报告进度。我这样做的原因是,如果NSURLSession不创建任何NSProgress对象(这是苹果公司声称的),那么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
正如您所看到的,fractionCompleted = 1.0没有额外的NSProgress对象,并且进度报告是正常的。
现在,我看不出fractionCompleted = 1.0的NSProgress是从哪里来的,如果它不是来自NSURLSession或下面的什么东西。(苹果声明,NSURLSession不会创建NSProgress对象。)我在iOS 7上看不到这种行为,只在iOS 8上(即使是GM版本)。
请注意,我使用的是带后台配置的NSURLSession!使用默认配置时,不会出现问题。
为什么这个“意外的”NSProgress对象在fractionCompleted = 1.0时出现?我是否使用了错误的NSProgress应用程序接口?是什么导致了iOS 7和8上截然不同的行为?
这里提供了示例代码:https://s3-eu-west-1.amazonaws.com/pg.test/pubtest/NSProgress-20140830.zip
提前感谢您的帮助。
发布于 2014-10-03 16:15:12
我们在上传进度时遇到了同样的问题。正如您所说的,创建任务的调用看起来是在创建一个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“块中创建的progress对象才会被添加为当前进程的直接子进程,而不是创建会话的进程。然后,来自被调用者的块的实现将如下所示:
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中的一个错误,或者这是否是预期的行为。
https://stackoverflow.com/questions/25787103
复制