Пользовательские издатели и подписчики
Создавайте собственные компоненты Combine.
«Пользовательские издатели и подписчики» — бесплатный урок Swift Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Swift Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Swift Academy содержит 4 уроков всего.
За пределами встроенных издателей
Фреймворк Combine включает множество издателей, но иногда требуется обернуть программный интерфейс, не использующий Combine, в издатель или обрабатывать значения с точным контролем обратного давления. Для этого необходимо самостоятельно реализовать протоколы издателя и подписчика.
Протокол издателя
Издатель объявляет типы Output и Failure и реализует receive(subscriber:), передавая подписку подключившемуся подписчику.
protocol Publisher {
associatedtype Output
associatedtype Failure: Error
func receive<S: Subscriber>(subscriber: S)
where S.Input == Output, S.Failure == Failure
}Роль подписки
Когда подписчик подключается, издатель создаёт объект Subscription. Объект subscription управляет спросом и доставляет значения, связывая издателя с подписчиком. Он соответствует протоколу Subscription, который расширяет Cancellable.
Пользовательская подписка
Объект subscription хранит подписчика и в ответ на запросы спроса выдаёт значения.
final class CountSubscription<S: Subscriber>: Subscription
where S.Input == Int {
private var subscriber: S?
private var current = 0
init(subscriber: S) {
self.subscriber = subscriber
}
func request(_ demand: Subscribers.Demand) {
var remaining = demand
while remaining > 0 {
remaining -= 1
remaining += subscriber?.receive(current) ?? .none
current += 1
}
}
func cancel() {
subscriber = nil
}
}Пользовательский издатель
Издатель просто создаёт подписку и передаёт её подписчику через receive(subscription:).
struct CountPublisher: Publisher {
typealias Output = Int
typealias Failure = Never
func receive<S: Subscriber>(subscriber: S)
where S.Input == Int, S.Failure == Never {
let subscription = CountSubscription(subscriber: subscriber)
subscriber.receive(subscription: subscription)
}
}Понимание спроса
Обратное давление — это механизм управления потоком в Combine. Подписчик запрашивает определённый объём Demand, а издатель не должен отправлять больше значений, чем было запрошено. Возврат спроса из receive(_:) увеличивает доступный объём.
Протокол подписчика
Пользовательский подписчик реализует три метода: получает подписку, затем каждое значение и после этого уведомление о завершении.
protocol Subscriber {
associatedtype Input
associatedtype Failure: Error
func receive(subscription: Subscription)
func receive(_ input: Input) -> Subscribers.Demand
func receive(completion: Subscribers.Completion<Failure>)
}Пользовательский подписчик
Здесь подписчик сначала запрашивает два значения, затем запрашивает ещё одно после каждого полученного значения и одновременно выводит их.
final class PrintSubscriber: Subscriber {
typealias Input = Int
typealias Failure = Never
func receive(subscription: Subscription) {
subscription.request(.max(2))
}
func receive(_ input: Int) -> Subscribers.Demand {
print("Value:", input)
return .max(1)
}
func receive(completion: Subscribers.Completion<Never>) {
print("Done")
}
}Адаптация делегатного интерфейса
Практическое применение пользовательских издателей — адаптация делегатного интерфейса или интерфейса обратных вызовов к Combine, чтобы сделать устаревший код пригодным для композиции. Вы используете store для хранения подписчика и передаёте вызовы делегата как вызовы receive(_:).
Предпочитайте субъекты, когда это возможно
Реализовывать протоколы вручную требуется редко. Для большинства случаев адаптации гораздо проще использовать PassthroughSubject или CurrentValueSubject — достаточно вызвать send(_:).
let subject = PassthroughSubject<Int, Never>()
subject
.sink { print($0) }
.store(in: &cancellables)
subject.send(1)
subject.send(2)Когда нужна собственная реализация
Выбирайте собственные реализации издателя и подписчика, когда требуется:
- тонкий контроль обратного давления
- эффективная адаптация сложного источника, не использующего Combine
- повторно используемые типобезопасные операторы
В остальных случаях правильным выбором будут субъекты и встроенные операторы.
Быстрая проверка
Проверьте свои знания о пользовательских издателях.
Повторение
Вы научились реализовывать основные протоколы Combine:
- Издатель создаёт подписку для каждого подписчика
- Подписка учитывает объём запроса (обратное давление)
- Подписчик получает подписку, значения и уведомление о завершении
- Для большинства задач адаптации предпочитайте субъекты
Понимание этих внутренних механизмов помогает разобраться в работе всего Combine.
Изучай Swift с ИИ-репетитором — бесплатно
Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.
- Курсы
- 122
- Уроки
- 409
Часто задаваемые вопросы
Урок «Пользовательские издатели и подписчики» бесплатный?
Да — полный текст урока «Пользовательские издатели и подписчики» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Swift Academy, подпишись на CoddyKit PRO. Курс Swift Academy содержит 4 уроков всего.
Чему я научусь в уроке «Пользовательские издатели и подписчики»?
Создавайте собственные компоненты Combine. Ты практикуешь Swift Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Swift Academy?
Предыдущий опыт не требуется. Swift Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Пользовательские издатели и подписчики»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Swift Academy?
Да. Каждый урок Swift Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Преобразование и объединение потоков
- Планировщики и потоки выполнения
- Операторы обработки ошибок
- Пользовательские издатели и подписчики