Pull to refresh

Comments 5

При этом у нас уже есть возможность загрузки обычных изображений из интернета, только они загружаются не через дополнительный сервис, а просто по URL.

Так мы пришли к очень простой идее: а что, если локальные ассеты тоже можно научиться загружать через URL?

Есть альтернатива — а что если удаленные ассеты загружать так же как локальные, через имеющийся уже сервис? У подхода есть несколько мощнейших преимуществ — а) не нужно разбираться с nsurlprotocol б) отлично ложится на уже имеющийся код в) ненужно ограничивать себя только URL в качестве идентификатора объекта.

Возможно, я не очень понятно рассказал в статье, попробую ещё раз.
Во-первых, AssetService работает только с PHImageManager и умеет загружать только локальные изображения. Не очень понятно, как сюда можно прикрутить работу с удалёнными изображениями, учитывая, что для них у нас в наличии есть только URL.
Во-вторых, как я уже сказал, в проекте messages нет никакого знания о наличии сервиса AssetService, т.к. он расположен в другом проекте, на который ссылки у messages нет. В цитате про жареный суп я описал, как можно было бы сделать, но затем так же описал почему нам это решение не понравилось.
В-третьих, мы лишаемся важных преимуществ работы с URL — поддержки кеширования изображения по URL «из коробки» и возможности удобной сериализации ключа (URL) с уже учтёнными параметрами вроде ширины, высоты, обрезки для сохранения этой информации в БД.
Во-первых, AssetService работает только с PHImageManager и умеет загружать только локальные изображения. Не очень понятно, как сюда можно прикрутить работу с удалёнными изображениями, учитывая, что для них у нас в наличии есть только URL.

Например, как-то так
var localAssetId = new LocalAsset("local-image-id");
var assetBytes = assetService.GetAsset(localAssetId);

var remoteAssetId = new RemoteAssetId(response.ImageUrl);
var remoteAssetBytes = assetService.GetAsset(remoteAssetId);

Сравним с подходом на NsUrlProtocol
var localAssetUrl = BuildLocalAssetUrl("local-image-id");
var assetBytes =  localAssetUrl.LoadAssetBytes();
var remoteAssetBytes = response.ImageUrl.LoadAssetBytes();

Утверждение — первый вариант решает аналогичную задачу и его проще понять и выяснить как он работает с помощью функции IDE «Go To Definition». Мне интересно услышать контраргументы.

Во-вторых, как я уже сказал, в проекте messages нет никакого знания о наличии сервиса AssetService, т.к. он расположен в другом проекте, на который ссылки у messages нет. В цитате про жареный суп я описал, как можно было бы сделать, но затем так же описал почему нам это решение не понравилось.

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

В-третьих, мы лишаемся важных преимуществ работы с URL — поддержки кеширования изображения по URL «из коробки» и возможности удобной сериализации ключа (URL) с уже учтёнными параметрами вроде ширины, высоты, обрезки для сохранения этой информации в БД.

Кеширование не теряется, загрузка удаленных картинок все также происходит через NSUrlConnection, кеш все таке участвует. Но вместо цепочки URL -> Protocol -> Connection -> Cache, есть цепочка Service -> Connection -> Cache. Поясняющий пример
//string id, can be stored in the db
var localAssetId = new LocalAsset("local-image-id");
//but it does not have to be a string, can be more complex **typed** data structure
//var localAssetId = new LocalImage("img-name", width: 10, height: 20);
var assetBytes = assetService.GetAsset(localAssetId); 
//above line load from cache, db or whenever

var remoteAssetId = new RemoteAssetId(response.ImageUrl);
var remoteAssetBytes = assetService.GetAsset(remoteAssetId); 
//Above line loads data via NSUrlConnection, uses HTTP cache if present.


Мое ИМХО — NsUrlProtocol нужен **только** если вы не контролируете потребителя данных и он может использовать только URL.
Кажется, что всё, что вы сделали — перевернули всё в обратную сторону. Чтобы сервис по загрузке и обработке изображений из галереи умел так же и ходить на сервер за удалённой картинкой. Не очень понимаю, чем это решение лучше предложенного. К тому же, вся остальная функциональность по обработке изображений (наложению фильтра, обрезке и т.д.) для удалённых картинок не нужна. Получается, что нужно делать ещё один отдельный сервис, который в зависимости от того, нужно ли загружать удалённую картинку или локальную, будет выполнять разную логику.

Ещё раз повторюсь, в проекте messages ничего не известно про наличие AssetService. И знания о нём в этом проекте не прибавилось. Мы используем URL определённого формата, а какой URL-протокол его обработает и обработает ли вообще — это отдельная задача.

Контраргументов против «Go To Definition» в IDE не приведу. Действительно удобная функция.

Кеширование теряется, поскольку загрузка через URLSession (NSURLConnection уже deprecated) осуществляется только для удалённых картинок. Для локальных, при использовании вашего решения, нужно придумывать что-то своё.
Плюс, как я уже упомянул в статье, у нас уже есть механизм загрузки удалённых изображений через URLImageView. Вы же предлагаете ради загрузки разного рода изображений его переделывать на работу с каким-то ранее неизвестным AssetService, чтобы вся загрузка шла через него. Кажется, что это знание добавлять вовсе необязательно.
Не освещён момент отправки сообщений товарищу майору.
Прикручена ли нейронная сетка или просто отсылается по рулам?
Учитывается ли возраст отправителя? Скажем — если отправителю 14 лет и он употребит слово КОЛУМБАЙН — мы точно знаем, что сообщение отправляется в ментовку. А если ребёнку будет 10 лет? А если будет 20?
Подскажите — очень интересно
Sign up to leave a comment.