Дата-ориентированный Combine
Перевод статьи подготовлен специально для студентов продвинутого курса «iOS Разработчик».
В предыдущем эпизоде мы успешно смоделировали поток значений, где к каждому значению был привязан один простой оператор (
В этой части мы рассмотрим еще несколько операторов, сделаем их
Прежде чем мы начнем их моделировать, нам нужно понять, какие существуют типы операторов.
Сайт ReactiveX разбивает их примерно на 10 категорий: создание, трансформация, фильтрация, объединение, обработка ошибок, вспомогательные, условные, математические/агрегатные, backpressure, connectable-observable и операторы для преобразования observable (To). Если вам интересно, у ReactiveX есть хорошее объяснение для каждого типа и оператора.
Этот тип оператора препятствует всем или некоторым (или никаким) из элементов потока продвигаться дальше по потоку на основе данного условия.
Мы также можем легко преобразовать этот кейс перечисления в Publisher.
Теперь оператор
Сохранение
В отличие от
Повторно публикует все элементы, которые соответствуют заданному замыканию.
Давайте рассмотрим метод
Его замыкание
Есть ли в Foundation что-то, что представляет логические условия и возвращает логическое значение? Напоминает что-нибудь?
Ответ —
Давайте продолжим и добавим
Все, что нам нужно, это фильтровать выражения типа
Как и планировалось, мы отправляем выражение в
Обратите внимание, что
Как вы можете наблюдать, Filter Stream добавляется в этот сохраненный массив операторов и преобразуется в Publisher, чтобы отфильтровать число 3 из вышестоящих значений.
В GIF-демо вы можете обнаружить, что список операторов довольно пуст. В ближайшие несколько недель мы собираемся заполнить его различными типами операторов: операторами трансформации,
Вы можете найти исходный код в этом combine-magic-swifui репозитории в папке combine-playground.
Ждем ваши комментарии и приглашаем на день открытых дверей по курсу.
Перевод статьи подготовлен специально для студентов продвинутого курса «iOS Разработчик».
В предыдущем эпизоде мы успешно смоделировали поток значений, где к каждому значению был привязан один простой оператор (
delay
).В этой части мы рассмотрим еще несколько операторов, сделаем их
Codeable
и, наконец, преобразуем их в паблишер Combine во время выполнения.Типы операторов
Прежде чем мы начнем их моделировать, нам нужно понять, какие существуют типы операторов.
Сайт ReactiveX разбивает их примерно на 10 категорий: создание, трансформация, фильтрация, объединение, обработка ошибок, вспомогательные, условные, математические/агрегатные, backpressure, connectable-observable и операторы для преобразования observable (To). Если вам интересно, у ReactiveX есть хорошее объяснение для каждого типа и оператора.
Примечание: Если вы не знакомы с RxSwift, Observable в RxSwift эквивалентен Publisher в Combine.В предыдущей части мы упомянули оператор
delay
, который относится к вспомогательному (utility
) типу. Сегодня мы сосредоточимся на сохранении двух фильтрационных (filtering
) операторов.Операторы фильтрации
Этот тип оператора препятствует всем или некоторым (или никаким) из элементов потока продвигаться дальше по потоку на основе данного условия.
dropFirst
dropFirst
останавливает передачу первых n
элементов. Мы можем просто добавить его в наше перечисление (enum) Operator
, учитывая его простоту.enum Operator {
case delay(seconds: Double)
case dropFirst(count: Int)
}
Мы также можем легко преобразовать этот кейс перечисления в Publisher.
extension Operator {func applyPublisher<T>(_ publisher: AnyPublisher<T, Never>) -> AnyPublisher<T, Never> {
switch self {
case .dropFirst(let count):
return publisher.dropFirst(count).eraseToAnyPublisher()
// пропустим остальные кейсы
}}}
Теперь оператор
dropFirst
можно сохранить и отобразить в списке операторов.Сохранение
dropFirst
схоже с оператором delay
. Возможно, фильтрация не так уж сильно отличается от вспомогательных операторов. Что ж, давайте попробуем еще один оператор, прежде чем мы сделаем такой вывод.Filter
В отличие от
dropFirst
, который имеет очень простые критерии фильтрации, оператор filter
использует замыкание (closure) вместо примитивного типа. Это уже случай посложнее. Как мы сохраняем и распространяем замыкание?filter(_:)
Повторно публикует все элементы, которые соответствуют заданному замыканию.
developer.apple.com
Давайте рассмотрим метод
filter
поближе.func filter(_ isIncluded: @escaping (Self.Output) -> Bool) -> Publishers.Filter<Self>
Его замыкание
isIncluded
принимает универсальный тип и возвращает логическое значение.Есть ли в Foundation что-то, что представляет логические условия и возвращает логическое значение? Напоминает что-нибудь?
Filter с NSPredicate
Ответ —
NSPredicate
. Если мы можем сохранить условия фильтрации в виде выражений в строковом формате, мы можем просто передать значение потока и использовать NSPredicate
для оценки результатов.Давайте продолжим и добавим
filter
в перечисление.enum Operator {
case delay(seconds: Double)
case dropFirst(count: Int)
case filter(expression: String)
}
Все, что нам нужно, это фильтровать выражения типа
%d !=3
или %@ != “D”
; следовательно, expression является соответствующим типом. Точно так же мы должны быть в состоянии переместить перечисление filter
в Publisher.extension Operator {
func applyPublisher<T>(_ publisher: AnyPublisher<T, Never>) -> AnyPublisher<T, Never> {
switch self {
case .filter(let expression):
return publisher.filter { value in
NSPredicate(format: expression,
argumentArray: [value])
.evaluate(with: nil) }.eraseToAnyPublisher()
// пропустим остальные кейсы
}}}
Как и планировалось, мы отправляем выражение в
NSPredicate
вместе со значением, отправляемым из Publisher.Обратите внимание, что
NSPredicate
принимает массив аргументов. Поэтому с некоторой модификацией он должен работать, даже когда значения принимают формат кортежей, что очень часто встречается в реактивных сценариях. Мы еще вернемся к этому в будущем, когда будем говорить о комбинированных операторах.Как вы можете наблюдать, Filter Stream добавляется в этот сохраненный массив операторов и преобразуется в Publisher, чтобы отфильтровать число 3 из вышестоящих значений.
В следующем эпизоде: Сохраняем операторы трансформации, Map и Scan
В GIF-демо вы можете обнаружить, что список операторов довольно пуст. В ближайшие несколько недель мы собираемся заполнить его различными типами операторов: операторами трансформации,
map
и scan
.Вы можете найти исходный код в этом combine-magic-swifui репозитории в папке combine-playground.
Ждем ваши комментарии и приглашаем на день открытых дверей по курсу.