【发布时间】:2017-03-08 15:50:55
【问题描述】:
我在前台通过NSURLSessionDownloadTask下载了一个文件,我需要在UI中显示当前的下载速度,
但我发现委托方法:URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite: 调用不顺畅:
这样我可以显示准确的当前下载速度。
我确定这不是由服务器引起的。当我通过 ASIHTTPRequest 下载相同的文件时,没关系,进度块被顺利调用。
有人知道为什么吗?谢谢!
更新 #0:
委托方法的实现:
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
_totalReceived += bytesWritten;
NSLog(@"receive: %8.2f KB, total receive: %8.2f KB", bytesWritten / 1024.f, _totalReceived / 1024.f);
CFTimeInterval now = CFAbsoluteTimeGetCurrent();
if (_lastDataReceiveAt > 0.f) {
CFTimeInterval delta = now - _lastDataReceiveAt;
NSLog(@"downloadtask: %p, speed: %8.2f KB/s; avg: %8.2f KB/s; delta time: %3.2fs",
downloadTask,
bytesWritten / 1024 / delta, _totalReceived / 1024 / (now - _beginsAt),
delta);
}
_lastDataReceiveAt = now;
//NSLog(@"downloading ... %.2f%%", totalBytesWritten * 100.f / totalBytesExpectedToWrite);
}
更新 #1:
嗨,@Rob,这是我的会话安装代码:
- (NSURLSession *)sessionWithIdentifier:(NSString *)identifier {
if (identifier == nil) {
NSString *bundleId = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"];
identifier = [NSString stringWithFormat:@"%@:///Downloader#%ld", bundleId, time(NULL)];
}
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
//config.protocolClasses = @[ASIURLProtocol.class];
return [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
}
并且,下载任务初始化:
_session = [self sessionWithIdentifier:nil];
NSURL *url = ...;
_task = [_session downloadTaskWithURL:url];
[_task resume];
CFTimeInterval now = CFAbsoluteTimeGetCurrent();
_beginsAt = now;
_lastDataReceiveAt = now;
_totalReceived = 0;
【问题讨论】:
-
我测试了一些明显的可能性(会话队列的优先级;并发队列 v 串行队列;下载任务 v 数据任务;确保应用程序已达到静止状态;等等),但我没有发现任何问题。与
URLSession的通话只有一些情节延迟。如果 ASIHTTPRequest 没有受此影响,那可能只是URLSession和使用的任何 ASIHTTPRequest 之间的差异。我只是建议坚持使用URLSession并使用一些尾随平均值或类似的东西,而不是依赖一个数据点来计算速度。 -
虽然我们在
NSURLSession委托方法中看到了一些偶发延迟,但通常以毫秒为单位,而不是 10 秒 (!)。我注意到您将主队列用于委托队列,如果您曾经阻塞主线程,您会看到您描述的那种行为。我建议将队列参数更改为nil,看看这 10 秒的延迟是否会消失。但是,如果是这样,您确实应该返回并确定阻塞主线程的原因,因为它永远不应该被阻塞。
标签: ios nsurlsession asihttprequest nsurlsessiondownloadtask