i'm getting confused trying to get progress from a Download Task with AFNetworking 2.0. I created a singleton object where I centralized my download operations (my app will download podcast files).
So, I have a PodcastManager class with this method, where I use a Podcast object created by me too:
- (void)downloadPodcast:(Podcast *)podcast completion:(CompletionBlock)completionBlock{
podcast.downloadState = DOWNLOADING;
NSURL *url = [NSURL URLWithString:podcast.enclosure];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSProgress *progress = [NSProgress progressWithTotalUnitCount:podcast.size];
NSURLSessionDownloadTask *downloadTask = [self.downloadManager downloadTaskWithRequest:request progress:&progress destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
NSURL *documentsDirectoryPath = [NSURL fileURLWithPath:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]];
//Return final path for podcast file
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
if (!error) {
//Handle success
}
else{
//Handle errors
}
}];
[progress addObserver:self forKeyPath:@"fractionCompleted" options:NSKeyValueObservingOptionNew context:nil];
[downloadTask resume];
if (completionBlock) {
dispatch_async(dispatch_get_main_queue(), ^{
completionBlock();
});
}
}
Right now, for debugging purposes I have this also in PodcastManager
:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"fractionCompleted"] && [object isKindOfClass:[NSProgress class]]) {
NSProgress *progress = (NSProgress *)object;
NSLog(@"Download at %f", progress.fractionCompleted);
}
}
I call the downloadPodcast:completion: method from a UITableViewController, where every cell represents a Podcast. What I'm trying to do is show a custom Progress View in the cell with the progress of the download of that podcast.
I know that AFNetworking 2.0 has a great UIProgressView that gets progress of a download task easily, but in my app I'm using this custom progress view https://github.com/danielamitay/DACircularProgress so I can't use this feature :(
Anyone can show me the way to do this right? Thanks
UPDATE: Well, I made some progress with this problem. Now I can access to the progress of the download from my custom cell using KVO. Using the method from AFURLSessionManager setDownloadTaskDidWriteDataBlock I get the current percentage of the download, and I save it in a property of the cell.
[[manager downloadManager] setDownloadTaskDidWriteDataBlock:^(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite) {
self.downloadPercentage = (float)totalBytesWritten/(float)totalBytesExpectedToWrite;
}];
Then with KVO i look over my property
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"downloadPercentage"] && [object isKindOfClass:[FDSEpisodeCell class]]) {
int percentage = self.downloadPercentage * 100;
NSLog(@"Percentage %d", percentage);
[self.downloadLabel setText:[NSString stringWithFormat:@"%d",percentage]];
}
}
My problem now is that I'm trying to show this percentage in a UILabel inside the cell, but although I change the label text, nothing changes. How can I refresh the label to show the current percentage?. I tried to use setNeedsDisplay but nothing happened. And if I use reloadData from the TableView, something weird happens and the view turns into blank.
Also, i tried with a NSTimer, but neither worked.
Use AFURLConnectionOperation -setDownloadProgressBlock:, updating the progress with the ratio of totalBytesRead over totalBytesExpectedToRead each time the block is called.
To update your UI element, just call the update through the main thread:
dispatch_async(dispatch_get_main_queue(), ^(void){
//Run UI Updates
});
Simple solutions for Swift:
let progressView: UIProgressView?
let sessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
let sessionManager = AFURLSessionManager(sessionConfiguration: sessionConfiguration)
let request = NSURLRequest(URL: url)
let sessionDownloadTask = sessionManager.downloadTaskWithRequest(request, progress: nil, destination: { (url, response) -> NSURL in
return destinationPath.URLByAppendingPathComponent(fileName) //this is destinationPath for downloaded file
}, completionHandler: { response, url, error in
//do sth when it finishes
})
Using UIProgressView
and setProgressWithDownloadProgressOfTask:
progressView.setProgressWithDownloadProgressOfTask(sessionDownloadTask, animated: true)
sessionDownloadTask.resume()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With