
Выполнение HTTP запросов — это один из самых важных навыков, которые необходимо получить при изучении iOS. В более ранних версиях Swift ( до версии 5) вне зависимости от того, формировали ли вы эти запросы «с нуля» или с использование известного фреймворка Alamofire, вы в конечном итоге получали сложный и запутанный код с callback типа completionHandler: @escaping(Result<T, APIError>) -> Void.
Появление в Swift 5 нового фреймворка функционального реактивного программирования Combine в сочетании с уже существующими URLSession и Codable предоставляет вам все необходимые инструменты для самостоятельного написания очень компактного кода для выборки данных из интернета.
Мы будем создавать «издателей» Publisher для выборки данных из интернета, на которые в дальнейшем можно будет легко «подписаться» и использовать при проектировании UI как с помощью UIKit, так и с помощью SwiftUI.
В SwiftUI это выглядит более эффектно, если не сказать «фантастически», так как разделение данных и View в SwiftUI осуществляется с помощью ObservableObject классов с @Published свойствами, изменения которых SwiftUI АВТОМАТИЧЕСКИ отслеживает и полностью «перерисовывает» View. В эти ObservableObject классы можно заложить определенную бизнес-логику приложения, так как некоторые из этих @Published свойств могут напрямую меняться такими «активными» элементами пользовательского интерфейса (UI) как текстовые поля TextField, Picker, Stepper, Toggle и т.д. Другие @Published свойства, напротив, могут быть «пассивными», являясь результатом синхронных и/ или асинхронных преобразований «активных» @Published свойств, но именно они то нас чаще всего и интересуют. Они обычно воспроизводятся в SwiftUI такими пассивными (UI) элементами, как текст Text, изображение Image, геометрические фигуры и т.д. Зависимость «пассивных» @Published свойств от «активных» @Published свойств очень просто описать с помощью Combine.
Чтобы было понятно, о чём идет речь, приведу конкретные примеры. Сейчас многие сервисы типа базы данных фильмов TMDb или агрегаторов новостей NewsAPI.org и Hacker News предлагают пользователям выбирать различные коллекции фильмов или наборы статей в зависимости от того, что вас интересует. В случае базы данных фильмов TMDb это могут быть фильмы, которые идут в данный момент в кинотеатрах, или популярные фильмы, или топовые фильмы, или фильмы, которые скоро появятся на экране. В случае агрегаторов новостей NewsAPI.org и Hacker News это могут быть последние новости, или новости в какой-нибудь категории — «спорт», «здоровье», «наука», «технологии», «бизнес», или новости от определенного информационного источника «CNN», «ABC news», «Bloomberg» и т.д., или новости, удовлетворяющие какому-то произвольному критерию. Свои желания для сервисов вы обычно «высказывает» в виде Endpoint, который формирует для вас нужный URL.
Так вот, используя фреймворк Combine, вы можете в ObservableObject классах с помощью очень компактного кода (в большинстве случаев не более 10-12 строк) однократно сформировать синхронную и/или асинхронную зависимость списка фильмов или статей (как «пассивных» @Published свойств) от Endpoint (как «активных» @Published свойств) в виде «подписки», которая будет действовать на протяжении всего «жизненного цикла» экземпляра ObservableObject класса. А далее в SwiftUI управлять только тем, что вы хотите увидеть, то есть выбирать нужную вам Endpoint: то ли это будут популярные фильмы, или фильмы, идущие в данный момент на экране, то ли это будут статьи с последними новостями или статьи в разделе «здоровье». Появление соответствующих фильмов или статей на вашем UI будет обеспечиваться АВТОМАТИЧЕСКИ этими ObservableObject классами и их пассивными @Published свойствами. В коде SwiftUI у вас никогда не возникнет необходимости явно запрашивать выборку фильмов или статей, вы будете управлять только тем, ЧТО вы хотите увидеть через Endpoint, вовсе не заботясь о результате, ибо он ВСЕГДА будет правильным и синхронным благодаря работе ObservableObject классов, которые исполняют роль View Model.
Я на трех конкретных примерах покажу, как это работает с помощью применения Combine для формирования HTTP запросов к различным сервисам и использование их в качестве View Model в SwiftUI.
Начнем с разработки приложения для взаимодействия с базой данных фильмов TMDb, а в последующем — приложений для взаимодействия с агрегаторами новостей NewsAPI.org и Hacker News. Во всех трех случаях будет действовать примерно одна и та же схема использования Combine , ибо в приложениях такого рода всегда приходится формировать СПИСКИ фильмов или статей, выбирать сопровождающие их «КАРТИНКИ» (images), ИСКАТЬ в базах данных нужные фильмы или статьи с помощью поисковой строки.
При обращении к сервисам типа базы данных фильмов TMDb или агрегаторов новостей NewsAPI.org и Hacker News могут возникать ошибки, например, связанные с тем, что вы задали неправильный ключ API-key или превысили допустимое количество запросов или еще что-то. Необходимо обрабатывать такого рода ошибки сервиса. Иначе пользователь вашего приложения попадёт в ситуацию, когда вдруг ни с того, ни с сего перестанут обрабатываться какие-либо запросы, оставляя пользователя в полном недоумении с пустым экраном. Поэтому надо уметь не только выбирать с помощью Combine данные из интернета , но и сообщать об ошибках, которые могут возникнуть при выборке. В этой статье мы уделим внимание обработке ошибок такого рода в Combine.
Читать далее →