2014-09-11 7 views
2

У меня есть дерево объектов NSProgress для контроля обработки данных, которая включает в себя загрузку файлов. Загрузка выполняется с использованием NSURLSession с настройкой фона.iOS 8 - Объект NSProgress с fractionCompleted = 1.0, созданный NSURLSessionDownloadTask, еще до возобновления задачи

Когда я запускаю этот процесс, самый верхний объект NSProgress сообщает о неожиданных деталях. Отлаживая проблему (и изолируя ее в приложении Hello World), Я обнаружил, что объект NSProgress создается в результате вызова [NSURLSession downloadTaskWithRequest:], а его свойство fractionCompleted равно 1.0 сразу после вызова вышеуказанного метода. Так как этот объект NSProgress получает часть моего дерева NSProgress, если смещение показывает цифры прогресса над ним в дереве.

В этом примере приложения я также начинаю фиктивную задачу фона параллельно с загрузкой, которая сообщает о прогрессе через объект NSProgress. Причина, по которой я сделал это, заключается в том, что при условии, что NSURLSession не создает никаких объектов NSProgress (что и утверждает Apple), в дереве 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 

В результате, отчеты о проделанной работе становится странно.

Если я закомментировать вызов, чтобы начать загрузку ([само 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 

Как вы можете видеть, что нет никаких дополнительных объектов NSProgress с fractionCompleted = 1.0 и отчет о ходе работы в порядке.

Теперь я не вижу, откуда этот NSProgress с fractionCompleted = 1.0, если он не из NSURLSession или чего-то под ним. (Apple заявила, что NSURLSession не создает объекты NSProgress.) Я не вижу этого поведения на iOS 7 только на iOS 8 (даже с выпуском GM).

Обратите внимание, что я использую NSURLSession с настройкой фона! При конфигурации по умолчанию проблема отсутствует.

Почему этот «неожиданный» объект NSProgress появляется с помощью fractionCompleted = 1.0? Я неправильно использую API NSProgress? Что вызывает совсем другое поведение в iOS 7 и 8?

Пример кода можно найти здесь: https://s3-eu-west-1.amazonaws.com/pg.test/pubtest/NSProgress-20140830.zip

Спасибо за любую помощь заранее.

ответ

3

Мы столкнулись с тем же вопросом с загрузкой прогресса. Как вы сказали, похоже, что вызов для создания задачи - это создание объекта 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:^NSProgress *(int64_t totalUnitCount) { 
    [currentProgress becomeCurrentWithPendingUnitCount:1]; 

    NSProgress *progress = [NSProgress progressWithTotalUnitCount:totalUnitCount]; 

    [currentProgress resignCurrent]; 

    return progress; 
} 

https://github.com/cgreen-mmf/AFNetworking/commit/a0703a4f82a47e6c56c11245e4d88846ffbd0b28

Я не ясно, если это ошибка в прошивке 8 или, если это предполагаемое поведение.