Как стать автором
Обновить
68.12
Surf
Создаём веб- и мобильные приложения

Как работать с реактивным кодом в 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.

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

var cancellable = Set<AnyCancellable>()

func sendURLRequest(_ urlRequest: URLRequest) {
	URLSession.shared.dataTaskPublisher(for: urlRequest) // 1
    	.map(\.data) // 2
    	.decode(type: LocationModel.self, decoder: JSONDecoder()) // 3
    	.mapError { $0.toServerError() ?? .unidentifiedError } // 4
    	.receive(on: DispatchQueue.main) // 5
    	.sink { completion in // 6
        	print("finished stream with: \(completion)")
    	} receiveValue: { value in
        	print("receive value: \(value)")
    	}
    	.store(in: &cancellable) // 7
}

Что происходит:

  1. Создание Publisher — оборачивает загрузку данных по URL.

  2. map(.data) — извлекает Data из ответа.

  3. decode — преобразует Data в модель LocationModel.

  4. mapError — конвертирует ошибку в нужный формат.

  5. receive(on:) — переключает поток на нужную очередь.

  6. sink — обрабатывает завершение и полученные данные.

  7. store(in:) — сохраняет подписку, чтобы поток не завершился сразу.

Такой подход делает код более читаемым, управляемым и реактивным.

Больше про iOS-разработку — в нашем Telegram-канале Surf Mobile Team. Кейсы, лучшие практики, новости индустрии, анонсы наших мероприятий и вакансий.

Присоединяйтесь!

Теги:
0
Комментарии0

Публикации

Информация

Сайт
surf.ru
Дата регистрации
Дата основания
Численность
201–500 человек
Местоположение
Россия