Что такое Optional Publisher в Combine?

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

Ответ

Optional Publisher — это специальный тип Publisher в фреймворке Combine, который создается из опционального значения с помощью свойства .publisher. Он испускает одно значение, если опционал не nil, и сразу завершается, либо завершается, не испуская значений, если опционал nil.

Создание и использование:

import Combine

// 1. Publisher из не-nil опционала
let optionalValue: Int? = 42
let cancellable1 = optionalValue.publisher // Тип: Optional<Int>.Publisher
    .sink(receiveValue: { value in
        print("Received value: (value)") // Выведет: Received value: 42
    })
// После испускания 42, Publisher завершается с .finished.

// 2. Publisher из nil опционала
let nilValue: String? = nil
let cancellable2 = nilValue.publisher
    .sink(
        receiveCompletion: { completion in
            print("Completed with: (completion)") // Выведет: Completed with: finished
        },
        receiveValue: { value in
            // Этот блок никогда не выполнится
            print("Received: (value)")
        }
    )
// Завершается с .finished, не испуская значений.

Практическое применение: Чаще всего используется для плавной интеграции опциональных значений в цепочки Combine операторов.

// Преобразование опционального результата запроса в поток
func fetchUser(id: Int) -> AnyPublisher<User?, Error> { ... }

fetchUser(id: 123)
    .flatMap { optionalUser -> AnyPublisher<User, Error> in
        // Разворачиваем опционал через его publisher
        return optionalUser.publisher
            .setFailureType(to: Error.self) // Приводим тип ошибки
            .eraseToAnyPublisher()
    }
    .catch { error in
        // Обработка ошибки, если fetchUser завершился с ошибкой
        return Just(User.placeholder)
    }
    .sink(receiveValue: { user in
        // Получаем гарантированно не-nil User
        print(user.name)
    })

Итог: Optional.Publisher — это мост между синхронным, опциональным миром и асинхронным, реактивным миром Combine.