Как стать автором
Обновить

Комментарии 8

Но ведь NSURLSession уже умеет работать с NSURLCache. И на самом деле городить свое собственное кеширование смысла нет. Достаточно правильно настроить кеширование запросов сессии (с обеих сторон: клиентской и серверной) и тупо дергать каждый раз запрос -- первый раз он скачает инфу с сервера, дальше будет брать из кеша, пока этот Кеш не почистится системой или не инвалидируется. просто и легко.

В описанном вами варианте используется dataTask, а не downloadTask. Apple же обозначает dataTask как средство загрузки небольшого кол-ва данных.

Хорошее пояснение, спасибо. А есть у Вас ссылки соответсвующие? И еще вопрос, а где-то указан этот барьер между небольшим и большим количеством данных? Бывают же и джейсоны на пару мегабайт, и картинки на сотни или даже десятки килобайт. Т.е.похоже, что тут не столько на размер надо обращать внимание, сколько на применимость как раз. Т.е.если нужен Кеш, пожалуйста, бери себе dataTask, нет? Ну, и если я буду использовать dataTask, а не downloadTask, Apple может зареджектить? Есть у вас чуть больше инфы на эту тему? Сам хочу разобраться.

Ух, вопрос у Вас конечно интересный. Почитать о позиции Apple по этому поводу можете вот здесь - Тыц

Чтобы понять допустимый объем данных, я думаю можно с другой стороны зайти т.к. ответа(официального) насколько я знаю нет. В dataTask (NSURLSessionDataTask) обмен идет через NSDAta, данные соответственно отправляются и загружаются с помощью объектов NSData и все данные сохраняются в оперативку, соответственно в фоновом режиме с ними работать нельзя (закрыли приложение, загрузка прекратилась), а downloadTask (NSURLSessionDownloadTask) пишет сразу на диск, может работать в фоне и работа ведется с файлами, что по моему мнению удобнее и производительнее. Например многопоточная загрузка 100+ изображений, весом в 20+ мб, через dataTask при неправильном проектировании, вполне может положить приложение (не проверял, но думаю это вполне возможно), а downloadTask ограничен только объемом диска по сути. Ну и в целом алгоритм мне более приятен. Я качаю на диск и получаю данные когда надо, память у Apple достаточно быстрая, проблем возникнуть не должно, параллельно/последовательно могу подконтрольно помещать данные в NSCache (тот который очищается при закрытии и самоочищается при необходимости), быстро, доступно, удобно да и вопрос с хранением решается сам по себе. А dataTask дает мне данные в оперативку (из них конечно я извлеку их быстрее), но теперь мне нужно это сохранить и даже если использовать автоматическое сохранение, процесс сохранения так или иначе присутствует. Понимаете к чему я клоню?) С downloadTask, я решаю, когда и что помещать в оперативку и получаю данные на диск, а dataTask, однозначно поместит данные в оперативку и лишает меня этого выбора.

В общем для коротких запросов, я использую dataTask и сохраняю в NSObject с последующим сохранением класса в UserDefault целиком (до 500кб идеально), например список тех же самых изображений. А все изображения, независимо от размера я качаю downloadTask. Плюс учитывайте, что SwiftUI и Image, не умеют в Data и так или иначе приходится сначала получать UIImage, а уже из него Image. Так что загрузка для меня приоритетнее.

Снова спасибо. Опять хороший ответ.

Итак, зафиксируемся:
1. dataTask умеет кешировать запросы из коробки
2. dataTask можно использовать для загрузки небольших изображений. Нигде явного лимита не указано. И лимит этот косвенно можно выявить из других признаков и рассуждений (хоть и не тех, что вы привели, по моему мнению, но об этом уже не будем).
вы с этим согласны.

Но вы опасаетесь, что dataTask сохраняет ВСЮ загруженную информацию сразу в память, что по Вашему мнению может привести к закрытию приложения системой. Вы, видимо, зацепились за первое предложение из вот этой ссылки, что сами и предоставили.

Ок, давайте разбираться.

Мы же с Вами уже разобрались, что dataTask кешурет данные. Т.е.они все же складываются на диск. А раз они складываются на диск, то с диска же они и читаются в оперативную память. Так? Уверен, что так.

Давайте теперь разберемся, а как же они читаются? А читаются они стандартным для iOS способом, применимым повсюду. Через NSData. В этом можно убедиться в конкретном примере, посмотрев тип данных первого параметра замыкания, вызываемого в результате выполнения dataTask.

Что ж открываем документацию, читаем:

The size of the data is subject to a theoretical limit of about 8 exabytes (1 EB = 10¹⁸ bytes; in practice, the limit should not be a factor).

Переведу и поясню. Теоретически, размер буфера в NSData ограничен 10ю в 18й степени (безумное число), а практически, вы не должны заботиться об этом лимите. Все работает для вас с такими объемами.

Как Вы думаете, как Apple удалось такого достичь на мобильных телефонах с гораздо-гораздо меньшим объемом оперативной памяти?

Все верно! Буфер NSData хранится на диске, а не в оперативной памяти. Это очень легко проверить, открыв какой-нить фильмец на пару гигабайт размером через NSData.

Таким образом, первое предложение, за которое вы зацепились, значит не что иное, как то, что данные вам возвращаются в виде объекта NSData, с которым вы можете работать, как-будто они находятся в оперативной памяти. Вам просто не нужно это делать самостоятельно, как если бы вы работали с downloadTask.

Что же касается замечания о том, что надо конструировать UIImage. Так он (как и Image в Свифт) работает поверх NSData все с тем же механизмом. Я это четко осознал, когда бил на тайлы 100МБ jpeg военную карту Москвы на 4S. Просто прикиньте, какой размер эта карта занимает попиксельно после декодирования jpeg. И тем не менее данная карта прекрасно отображалась на экранчике мобильного телефона. Правда, плохо масштабировалась, что я позже и решал тайлингом.

Таким образом, ваши опасения о том, что dataTask истратит всю вашу оперативную память, выглядят сомнительно. В Apple не глупые люди сидят и все для вас они уже сделали. Смысла повторять их работу я пока не увидел.

Есть еще аргументы для меня и сообщества в пользу ручного кеширования и повторения работы Apple самостоятельно вместо того, чтобы взять коробочное решение?

Спасибо за развернутый ответ столь исключительного качества. Вы дали мне много пищи для ума и признаться, я открыл для себя много нового, углубившись в изучение этого вопроса.

Из объективных преимуществ, могу выделить только возможность производить загрузку в фоне.

Предположительное преимущество, я его не проверял, но обязательно проверю в будущем. Я склонен полагать, что dataTask, все же кэширует по следующей модели сеть -> озу -> диск, в то время, как downloadTask безоговорочно качает на диск мимо озу, это я проверял и приложение выдержало мои безумные тесты без каких либо проблем.

Мое субъективное преимущество для меня лично - присутствие контроля.

Это знаете, как коробка автомат и механика, вопрос предпочтений. Мне нравится контролировать все этапы, downloadTask дает мне больше возможностей в этом плане, но это скорее вопрос психологического комфорта.

С Вами в целом согласен, коробочное решение от Apple чаще предпочтительнее нежели велосипед, тут и обсуждать нечего. Но я Вам и не доказываю, что мой вариант лучше, а мотивирую свой выбор в его пользу.

Apple очень круто подходят к проектированию, но я часто предпочитаю свои решения, понимаю, что это может выглядеть глупо. Мотивация в том, что я адепт принципа kiss и люблю самодостаточные конкретные решения. Как пример, могу привести реализацию ожидания данных с разных запросов через didSet, и буферным свойством, которое сигнализирует о готовности (чтобы не выполнять избыточный код в наблюдаемом). Это самый быстрый и производительный способ, который мне удалось использовать в формате небольшого приложения. Понятно, что на большем проекте количество велосипедов, просто нивелируют прирост производительности, но в рамках одного конкретного, многокомпонентного запроса, это получается более быстрым решением.

Спасибо. Снова хорошие мысли.

Вопрос контроля. Не смотрел на проблемы собственных реализаций с этой стороны. А ведь действительно. Многие могут реализовывать свои решения потому, что не понимают, как управлять тем, что есть у Apple. Что касается управления кешом через dataTask, так я, наверное, и не знаю-то, как это делается в деталях ^.^ Вы тоже натолкнули меня на хорошие мысли, спасибо за это.

Ну, и желаю Вам опубликовать статью по итогам исследований нативного кеширования. Материала должно набраться много и очень толкового.

По SwiftUI можно попробовать лекции Стэнфордского университета - "CS193p (Developing Applications for iOS using SwiftUI)"

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории