I have a piece of working code that downloads a file using NSURLDownloadTask, that tracks the download progress using URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:. The progress indicator fill in smoothly - it looks good. I am now refactoring the code to not use session and task delegate methods for various reasons. For progress indication I switched to KVO on the download taks's countOfBytesReceived (the documentation notes that all task properties support key-value observing). It does work, but it looks pretty bad - the intervals between progress incrementation take too long and sometimes never show up at all. To my understanding, I should not explicilty dispatch the task to a background queue - it should be done by the session task itself (or should I?).
Example code follows (please excuse the vintage ObjC syntax...)
- (void)download:(NSURL*)url {
self.task = [session downloadTaskWithURL:url completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
[self stopObservingProgressChanges];
// ...
}];
[self startObservingProgressChanges];
[self.task resume];
}
- (void)startObservingProgressChanges {
__weak WTPackageDownloader *weakSelf = self;
[self.task addObserver:self
keyPath:@"countOfBytesReceived"
options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
block:^(MAKVONotification *notification) {
weakSelf.package.progress.totalUnitCount = weakSelf.task.countOfBytesExpectedToReceive;
weakSelf.package.progress.completedUnitCount = weakSelf.task.countOfBytesReceived;
}];
}
- (void)stopObservingProgressChanges {
[self.task removeObserver:self keyPath:@"countOfBytesReceived"];
}