Подтвердить что ты не робот

Как добиться загрузки в AFNetworking 2.0?

Я использую AFURLSessionManager для создания новой задачи загрузки:

AFURLSessionManager* manager = ...

NSProgress* p = nil;
NSURLSessionDownloadTask* downloadTask =
        [manager downloadTaskWithRequest:request
                                 progress:&p
                              destination:^NSURL*(NSURL* targetPath, NSURLResponse* response) {...}
                        completionHandler:^(NSURLResponse* response, NSURL* filePath, NSError* error) {...}
        ];
[downloadTask resume];

Файл загружается в порядке, однако, как мне получить уведомления о ходе работы?

p всегда равно nil. Я зарегистрировал issue для этого.

Я также попытался вызвать setDownloadTaskDidWriteDataBlock в диспетчере, и там есть уведомления о ходе выполнения, но я получаю их все сгруппированные после загрузки файла.

Похоже, эта область по-прежнему немного ошибочна в AFNetworking 2.0

Любые идеи?

4b9b3361

Ответ 1

Вы должны наблюдать свойство fractionCompleted вашего объекта NSProgress, используя KVO:

NSURL *url = [NSURL URLWithString:@"http://www.hfrmovies.com/TheHobbitDesolationOfSmaug48fps.mp4"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFHTTPSessionManager *session = [AFHTTPSessionManager manager];
NSProgress *progress;
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request progress:&progress destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
    // …
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
    [progress removeObserver:self forKeyPath:@"fractionCompleted" context:NULL];
    // …
}];

[downloadTask resume];
[progress addObserver:self
            forKeyPath:@"fractionCompleted"
               options:NSKeyValueObservingOptionNew
               context:NULL];

Затем добавьте метод наблюдателя:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"fractionCompleted"]) {
        NSProgress *progress = (NSProgress *)object;
        NSLog(@"Progress… %f", progress.fractionCompleted);
    } else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

Конечно, вы должны проверить параметры keyPath и/или object, чтобы решить, есть ли объект/свойство, которое вы хотите наблюдать.

Вы также можете использовать метод setDownloadTaskDidWriteDataBlock: из AFURLSessionManager (из которого наследуется AFHTTPSessionManager), чтобы установить блок для получения обновлений хода выполнения загрузки.

[session setDownloadTaskDidWriteDataBlock:^(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite) {
    NSLog(@"Progress… %lld", totalBytesWritten);
}];

Этот метод AFNetworking отображает метод URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite: из протокола NSURLSessionDownloadDelegate в более удобный блок-механизм.

BTW, реализация Apple KVO сильно нарушена. Я рекомендую использовать лучшую реализацию, такую ​​как предложенная Майком Эшем с MAKVONotificationCenter. Если вы заинтересованы в том, чтобы прочитать, почему Apple KVO нарушена, прочитайте Замечание о ключевом значении, сделанное справа Майком Эшем.

Ответ 2

Я столкнулся с аналогичной проблемой и нашел решение.

Проверьте ссылку ниже: http://cocoadocs.org/docsets/AFNetworking/2.0.1/Categories/UIProgressView+AFNetworking.html

#import <AFNetworking/UIKit+AFNetworking.h>

и используйте дополнительный метод, доступный вашему UIProgressView

setProgressWithDownloadProgressOfTask: анимированные:

Как я это сделал:

NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request  progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response){
    NSURL *documentsDirectoryPath = [NSURL fileURLWithPath:[NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES) firstObject]];
    return [documentsDirectoryPath URLByAppendingPathComponent:[targetPath lastPathComponent]];
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error){
    NSLog(@"File downloaded to: %@", filePath);

}];

[self.progressView setProgressWithDownloadProgressOfTask:downloadTask animated:YES];
[downloadTask resume];

Ответ 3

Простые решения для Swift:

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
        })

Теперь у вас есть 2 варианта:

  • Использование UIProgressView и setProgressWithDownloadProgressOfTask:

    progressView.setProgressWithDownloadProgressOfTask(sessionDownloadTask, animated: true)
    
  • Используя AFURLSessionManager и setDownloadTaskDidWriteDataBlock:

    sessionManager.setDownloadTaskDidWriteDataBlock { session, sessionDownloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite in
    
        let progress = Float(totalBytesWritten)/Float(totalBytesExpectedToWrite)
            //do sth with current progress
    }
    

В конце не забывайте о:

sessionDownloadTask.resume()

Ответ 4

Для загрузки файла с состоянием выполнения используйте этот код

 NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];

NSURL *URL = [NSURL URLWithString:@"http://..."];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];


NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress)
{
    NSLog(@"Progress: %f", downloadProgress.fractionCompleted);
    if (progressBlock) {
                    progressBlock(downloadProgress);
                }
} destination:^NSURL *(NSURL *targetPath, NSURLResponse *response)
{
    NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
    return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error)
{
    if (response && successBlock) {
                    successBlock(response,filePath);
                }
    NSLog(@"File downloaded to: %@", filePath);
}];

[downloadTask resume];