Программирование
Стриминг изменений с помощью Observations
Появление типа Observations знаменует собой значительное улучшение возможностей Swift по наблюдению за данными, особенно для разработчиков, использующих Swift Concurrency.
Несколько лет назад Apple представила фреймворк Observation. Он стал основным инструментом для построения наблюдаемых моделей, заменив Combine. На этой неделе мы расскажем о новой части фреймворка под названием Observations.
Основным недостатком фреймворка Observation была его неспособность преобразовывать наблюдаемые типы в асинхронные потоки, что позволяло бы нам наблюдать за ними так же, как мы это делаем с Publisher в Combine.
func startObservation() {
withObservationTracking {
render(store.state)
} onChange: {
Task { startObservation() }
}
}
Хотя фреймворк Observation предлагает функцию withObservationTracking, которая позволяет нам вручную отслеживать изменения в наблюдаемом типе, он все еще имеет некоторые ограничения.
Во-первых, рекурсивное наблюдение приходится инициировать вручную, поскольку оно срабатывает только при первом изменении. Во-вторых, оно не вписывается в мир Swift Concurrency, поскольку его нельзя использовать как асинхронный поток внутри асинхронного цикла for. К счастью, Apple исправила все эти недостатки, представив новый тип Observations. Он предназначен для работы в паре с макросом Observable.
let store = Store() // Observable
struct State {
let items: [String]
let isLoading: Bool
}
let streamOfStates = Observations {
let state = State(
items: store.items,
isLoading: store.isLoading
)
return state
}
for await state in streamOfStates {
render(state)
}
Тип Observations соответствует протоколу AsyncSequence, что позволяет использовать экземпляры этого типа внутри асинхронного цикла for. Замыкание, которое мы используем для инициализации экземпляра типа Observations, неявно отслеживает все свойства наблюдаемых экземпляров, с которыми вы работаете.
Как видно из примера ниже, мы создаём новое состояние внутри замыкания. Мы работаем со свойствами items и isLoading типа Store, соответствующего протоколу Observable.
Мы наблюдаем за создаваемыми экземплярами типа State внутри асинхронного цикла for. При каждом изменении свойств items и isLoading он создаёт новый экземпляр типа State, который мы асинхронно извлекаем внутри цикла.
Тип Observations достаточно интеллектуален для использования транзакционных обновлений, что означает, что он не генерирует значение для каждого изменения. Он может группировать обновления, когда изменения происходят одновременно в свойствах items и isLoading.
extension Observable {
func stream<Value: Sendable>(
of keyPath: KeyPath<Self, Value>
) -> any AsyncSequence<Value, Never> {
Observations {
self[keyPath: keyPath]
}
}
}
Вот небольшое расширение протокола Observable, позволяющее вам легко создавать асинхронные последовательности для KeyPath для наблюдаемого типа.
for await items in store.stream(of: \.items) {
print(items)
}
Появление типа Observations знаменует собой значительное улучшение возможностей Swift по наблюдению за данными, особенно для разработчиков, использующих Swift Concurrency. Он стирает разрыв между реактивными обновлениями и современными асинхронными шаблонами, упрощая создание понятных, эффективных и отзывчивых пользовательских интерфейсов. Надеюсь, вам понравится эта публикация. Подписывайтесь на автора в Твиттере и задавайте вопросы по теме. Спасибо за прочтение, увидимся на следующей неделе!
-
Аналитика магазинов4 недели назад
Мобильный рынок Ближнего Востока: исследование Bidease и Sensor Tower выявляет драйверы роста
-
Видео и подкасты для разработчиков4 недели назад
Разбор кода: iOS-приложение для управления личными финансами на Swift. Часть 1
-
Новости4 недели назад
Видео и подкасты о мобильной разработке 2025.47
-
Разработка4 недели назад
100 уроков о том, как я довёл своё приложение до продажи за семизначную сумму

