2

Я знаю, что могу использовать dataTaskWithURL:completionHandler:, чтобы получить данные в блоке completeHandler, но это блокирует методы делегата от стрельбы, и мне нужен метод didReceiveData:, так как я настраиваю индикатор прогресса.Как получить данные из готовой `NSURLSessionDataTask`?

Я полностью в недоумении, как получить загруженные данные после их завершения. Что такое метод делегата, эквивалентный блоку завершения? didCompleteWithError, похоже, не возвращает NSData.

Мне не нужно вручную объединять данные в didReceiveData, не так ли? Это кажется очень хромым, когда completeHandler просто передает это вам. Я бы не прочь сделать это, если бы не тот факт, что я мог одновременно загружать 50+ вещей, поэтому отслеживание всех этих частичных данных кажется болью в заднице. Должен ли я просто переключиться на NSURLSessionDownloadTask?

+0

Я написал класс загрузчика (используя задачу загрузки), который может вам помочь: https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/bk2ch24p842downloader/ch37p1099downloader/MyDownloader.m – matt

+0

Итак, это - реализация того, что [Роб имеет в виду] (http://stackoverflow.com/a/21925050/2005643) в своем последнем абзаце? –

+0

Вы посмотрели? Вы посмотрели, что я сказал в своем предыдущем комментарии? – matt

ответ

5

Да, вы должны вручную объединить данные (или вы можете передать его в файл, если он действительно большой, и вы не хотите, чтобы он занимал память).

Итак, didReceiveData метод будет возвращать данные, как это происходит. Так что вы должны иметь экземпляр NSMutableData (например, в didReceiveResponse), к которому didReceiveData будет добавлять данные, как это происходит. Когда didCompleteWithError называется, предполагая ошибка nil, вы можете быть уверены, что ваш NSMutableData теперь содержит все полученные данные. Как вы отметили, задача состоит в том, чтобы отслеживать все 50+ загрузок, поэтому я поддерживаю словарь с ключом идентификаторов задач, чтобы отслеживать, к чему добавить данные. (Лично я считаю, что это дефект дизайна, который NSURLSession выполняет задачу, загружает и загружает делегатов на уровне сеанса, вместо того, чтобы позволить нам создавать экземпляры отдельных объектов делегата для каждой задачи. Но мы застряли в том, что у нас есть.)

Если вы просто загружая данные, то NSURLSessionDownloadTask является прекрасной альтернативой (и является более эффективным с точки зрения использования памяти, чем просто добавление к NSMutableData экземпляров), и вы можете предположительно также использовать фоновый сеанс, если вы хотите (который вы не можете с NSURLSessionDataTask).

Наконец, если вы действительно делаете 50+ загрузок, вы можете рассмотреть возможность переноса задач загрузки в подклассу NSOperation, чтобы вы могли ограничить количество выполняемых одновременно, не рискуя иметь какой-либо тайм-аут.

+0

Кстати, авторы AFNetworking сообщают (см. [Номер 1504] (https://github.com/AFNetworking/AFNetworking/issues/1504)), что предстоящий выпуск будет обертывать объекты 'NSURLSessionTask' в' NSOperation' подкласс, поэтому, если вы не хотите писать свой собственный класс для этого (как это делали некоторые из нас), вы можете следить за обновлениями AFNetworking. – Rob

+0

Хм, на самом деле я сомневаюсь, что я когда-нибудь буду делать больше 10. Стоит ли обертывать его в NSOperations? Думаю, мне следовало бы просто проверить и посмотреть. –

+0

Чрезвычайно образовательный ответ. - Я действительно беспокоюсь, потому что документация, похоже, предполагает, что с задачей данных вы не можете полагаться на части данных, чтобы они поступали по порядку - и в этом случае простое добавление к изменяемым данным каждый раз не срабатывало. – matt

Смежные вопросы