Combine: 3 примера использования Publishers и Subscriber
На конференции WWDC 2019 был представлен новый фреймворк Combine. Всё последнее десятилетие среди программистов становились популярными декларативный и Event-based подходы к разработке приложений, т. к. они дают преимущество в скорости разработки приложений.
Combine предоставляет следующие возможности: 1. Асинхронное выполнение кода. 2. Составные компоненты. 3. Более простой мультитрединг. 4. Кроссплатформенный код.
Combine позволяет выполнять код «реактивно».
Publishers and Subscribers
Основой Combine является 2 концепции: 1. Subscriber выполняет роль Observer. 2. Publisher выполняет роль Observable.
Самый короткий пример их использования:
import Combine let pub = Just("Hello") _ = pub.sink { print($0) }
Объявляем константу, где в структуру Just оборачивается строка "Hello", — это наш паблишер, который оповестит только раз. Ниже добавляем подписку с замыканием с помощью метода sink. И этот пример напечатает в итоге строку Hello.
@Published Property Wrapper
В Swift 5.1 появилась возможность использовать Property Wrappers, которые изначально назывались Property Delegates. Это очередная обёртка в виде структуры, позволяющая добавлять на чтение или запись свойства (property) дополнительное поведение. Combine же даёт возможность использовать их через @Published.
import Foundation import Combine class ObjectWithPublisher { @Published var someString: String = "" } var obj = ObjectWithPublisher() obj.$someString.sink(receiveValue: { print ("\($0)") }) obj.someString = "Hello Combine!"
Обращаться к таким врапперам можно, используя $ перед свойством. Как и в прошлом примере, мы добавляем Subcriber с помощью метода sink, но свойство мы обновляем позже подписки. В итоге этот пример распечатает нам “Hello Combine!”
Subjects
В Combine такие сущности, как Subject также являются паблишерами, которым мы можем посылать события. Сейчас у нас есть 2 вида Subjects: 1. PassthroughSubject, с помощью которого вы получите все события, которые случились после вашей подписки. 2. CurrentValueSubject — получите всё тоже, что и с помощью PassthroughSubject, но также и предыдущее или инициализированное значение
import Combine let subj = PassthroughSubject<String, Never>() let pub = subj.eraseToAnyPublisher() subj.send("Hello") let subscriber = pub.sink(receiveValue: { print($0) }) subj.send("Combine") subj.send("!")
Объявление Subjects требует от нас, чтобы кроме выходного типа мы также указали тип для ошибки, можем просто указать здесь Never. Функция
Combine !
import Combine let subj = CurrentValueSubject<String, Never>("Bonjour") let pub = subj.eraseToAnyPublisher() subj.send("Hello") let subscriber = pub.sink(receiveValue: { print($0) }) subj.send("Combine") subj.send("!")
Использование CurrentValueSubject отличается тем, что нам нужно указать начальное значение. И результат мы получим :
Hello Combine !
Если же мы не закомментируем первое отправление до подписки, то вместо Hello нам придёт начальная строка Bonjour.