Swift. Менеджер сетевых запросов.

По крайней мере в последнее десятилетие, количество приложений, которым требуется доступ в интернет, неимоверно возросло. Причем для большинства проектов требуется только выполнение REST запросов и загрузка изображений, с созданием preview. В связи с чем, необходим своего рода менеджер сетевых запросов для загрузки данных из сети. Далее будет представлен NetworkManager, с помощью которого выполняются REST запросы, а также загружаются файлы, в том числе и изображения.

Задача

Необходимо разработать менеджер сетевых запросов для выполнения REST запросов, загрузки и кэширования и создания preview изображений. При этом необходимо, чтобы была возможность обрабатывать появление/отсутствие соединения и конфигурировать кэширование. Решение должно использовать новую систему concurrency, представленную в iOS 15.

REST запросы

При разработке решения следует вспомнить основные постулаты ООП — инкапсуляция, абстракция, наследование и полиморфизм.

Ниже представлен базовый класс, с помощью которого конфигурируется сессия (URLSession), расположена логика по обработке ответа сервера (URLResponse), от которого будут наследоваться конкретные загрузчики (модули) и который зависит только от Foundation framework.

Не стоит удивляться наличию перечисления HTTPStatusCode, поскольку это достаточно стандартный набор констант, возвращаемых серверов в URLResponse.

Далее к разработке решения.

Наиболее часто используемым является DataLoader. Поскольку с его помощью, выполняются REST запросы, то предпочтительно, чтобы данный модуль еще и выполнял сериализацию/десериализацию запросов.

UrlCreatable — это интерфейс для создания URL, котрый реализуют типы String и URL.

С HTTPMethod и HTTPHeader тоже все понятно — это тоже стандартный набор констант, используемых в запросе, отправляемом на сервер (URLRequest).

А вот создание самого запроса программировать уже несколько сложнее, так как нужно сериализовать параметры либо в query строку, либо в httpBody data.

Может показаться, что работа с параметрами запроса несколько запутана, но на деле это набор ключ: значение, сериализованные по определенным правилам, заданным в структуре Parameters.

На этом ядро NetworkManager готово. В очередной раз обращаю внимание, что ядро не зависит от UI фреймворков, а значит легче поддерживается.

Загрузка файлов

Имея такое ядро невероятно просто добавить новый модуль — FileLoader для загрузки файлов.

Загрузка изображений

С загрузкой изображений все несколько сложнее, поскольку необходимо добавить логику кэширования и создания preview. Но, очень важно, чтобы эта логика выполнялась в потоке, параллельном main, иначе возможны тормоза в работе UI. По этой причине так называемый ImageLoader является actor, поскольку в этом случае будет использоваться Task данного actor, а не MainActor. Также, поскольку уже идет работа с изображениями, добавлена зависимость от UI фреймворка — SwiftUI.

Если с созданием preview все понятно — достаточно вызвать метод byPreparingThumbnail(ofSize:), то с логикой кэширования нужно разобраться. Ведь использовать NSCache<KeyType, ObjectType> ошибочно, так как изображение и так будет сохранено в ОЗУ, при наполнении модели. А вот для того, чтобы изображения были кэшированы в постоянную память, требуется некоторый ImagesStorage объект, сохраняющий в постоянную память и загружающий из неё.

Внимательного читателя может удивить использование hash свойства NSString вместо стандартного md5 hash. В этом месте разработчик позволил себе сделать паузу и выпить чашечку хорошего кофе, после чего запрограммировал наиболее простое решение.

Этот объект унаследован от CachedStorage, который сохраняет файлы в постоянную память и загружает из неё и реализует NetworkCache интерфейс.

Пример использования

Несмотря на кажущуюся простоту решения, в результате на руках мощный инструмент для загрузки как данных:

так и изображений:

Заключение

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

  1. https://developer.apple.com/documentation/foundation/urlsession
  2. https://developer.apple.com/documentation/foundation/urlrequest
  3. https://developer.apple.com/documentation/foundation/urlresponse
  4. https://github.com/Alamofire/Alamofire
  5. https://developer.apple.com/wwdc22/

--

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Ace Rodstin

Ace Rodstin

More from Medium

UserDefaults in Swift

Use Read Write lock to solve data racing in Swift

Working with Network Request in Swift

Swift| Property Observers