Как работать с реактивным кодом в iOS на примере Combine
Пожалуй, каждый iOS-разработчик видел в требованиях вакансий «знание фреймворков RxSwift, RxCocoa». Эти инструменты основаны на концепции реактивного программирования.
Реактивное программирование, как следует из названия, основано на реакции на событие: пользователь взаимодействует с интерфейсом и ждёт реакцию от приложения. Этот подход популярен в фронтенд-разработке, в том числе на iOS.
Мы в Surf долгое время избегали «реактивщины» в приложениях. Во-первых, это лишние зависимости. Во-вторых, подобные библиотеки несут в себе не только преимущества, но и проблемы с дебагом, сложностью поддержки кода и так далее.
Однако с выходом Combine и SwiftUI, мы решили начать внедрять реактивный подход в наши приложения. Благо, теперь не нужны сторонние решения: хватит того, что предоставляет Apple. Давайте посмотрим, как можно работать с реактивным кодом.
Главные элементы Combine, с которыми происходит работа:
1) Publisher — издатель
Протокол, указывающий, что тип может передавать последовательность значений со временем. Publisher предоставляет данные только подписчику (Subscriber) и делает это, когда данные становятся доступны. Без подписки Publisher не активен.
Publisher описывается двумя ассоциированными типами: <Output, Failure>
Output — тип выдаваемых значений
Failure — тип возможной ошибки. Если ошибок быть не может, используется Never.
2) Subscriber — подписчик
Отвечает за запрос и получение данных от издателя, а также за обработку ошибок. Имеет типы <Input, Failure>:
Input — тип входных данных
Failure — тип ошибки
Subscriber сам инициирует запрос и управляет объёмом поступающих данных. Основные способы обработки:
sink(receiveCompletion:receiveValue:)Принимает два замыкания: первое вызывается при завершении (успешно или с ошибкой); второе — при получении значений.
assign(to:on:)Присваивает полученные значения свойству объекта по keyPath.
3) Operators — операторы
Методы, преобразующие данные и потоки. Операторы — это промежуточное звено между издателем и подписчиком. С их помощью строятся цепочки обработки, трансформации и фильтрации данных.
4) Subjects — субъекты
Особый вид Publisher. Объекты, реализующие этот протокол, могут отправлять значения подписчикам через метод .send(_).
Subjects полезны для интеграции императивного кода: позволяют вручную вставлять значения в поток.
Управление подпиской
Publisher продолжает отправку до завершения или ошибки. Если подписка больше не нужна, её можно отменить с помощью метода cancel(). Все подписчики реализуют протокол Cancellable.