Что такое Subject в Combine?

«Что такое Subject в Combine?» — вопрос из категории Реактивное программирование, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Subject — это специальный тип Publisher в фреймворке Combine, который позволяет отправлять значения подписчикам вручную через метод send(). Он сочетает возможности Publisher (отправка значений) и Subscriber (приём значений), что делает его удобным для адаптации императивного кода к реактивному потоку.

Основные типы Subject

  • PassthroughSubject<Output, Failure> — передаёт значения подписчикам, но не хранит текущее значение. Новые подписчики получают только значения, отправленные после подписки.
  • CurrentValueSubject<Output, Failure> — хранит текущее значение (доступно через свойство value) и немедленно отправляет его новым подписчикам при подписке.

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

import Combine

// Создание Subject
let subject = PassthroughSubject<String, Never>()

// Подписка
let subscription = subject.sink { value in
    print("Получено: (value)")
}

// Ручная отправка значений
subject.send("Привет") // Вывод: Получено: Привет
subject.send("Мир")    // Вывод: Получено: Мир

// Завершение потока
subject.send(completion: .finished)

Ключевые особенности

  • Управляемая отправка: значения отправляются явно через send(_:).
  • Множественные подписчики: один Subject может иметь несколько подписок.
  • Завершение потока: можно завершить с ошибкой (send(completion: .failure(error))) или успешно (send(completion: .finished)).
  • Мост между императивным и реактивным кодом: часто используется для обёртки делегатов, callback-ов или событий UI в реактивные потоки.