Разработка
Миграция Ice Cubes на фреймворк SwiftUI Observation
Фреймворк Observation — это огромное улучшение для SwiftUI. Он прост и избавляет от головной боли по сравнению с предыдущим потоком данных.
Если вы задавались вопросом, стоит ли вам переводить свое SwiftUI-приложение на новый фреймворк Observation, то вы попали по адресу.
Недавно я перевел Ice Cubes, мой клиент Mastodon с открытым исходным кодом, только на iOS 17+, поскольку полностью перевел его на новые потоки данных фреймворка Observation.
Если вы не знакомы с Ice Cubes, не стесняйтесь прочитать мою предыдущую статью о нем.
Основные выводы
- Это не сложное упражнение. Я выполнил его за несколько часов.
- Это позволило исправить ошибки, а не создать новые.
- Улучшение производительности заметно и стоит того.
В Ice Cubes активно используется ObservableObject, инжектируемый как EnvironmentObject. При прежнем способе работы потока данных любая мутация свойства @Published вызывала обновление представления, независимо от его использования в теле представления. Поэтому нужно было очень внимательно следить за тем, какой EnvironmentObject извлекать и какое property в нем обновлять.
Я потратил много времени в Ice Cubes, чтобы убедиться, что я не обновляю слишком много свойств одновременно или слишком часто и т.д.. Но иногда этого нельзя избежать. Отсутствие необходимости беспокоиться (слишком сильно) об этом просто невероятно и экономит массу времени, потраченного в профилировщике на попытки понять, что происходит.
Существенное различие между предыдущим потоком данных и новым фреймворком Observation заключается в том, что представления SwiftUI будут себя только тогда, когда в нем используется наблюдаемое свойство. Оно не будет обновляться только потому, что на объект ссылаются в других частях проекта как @State или @Environment.
Вы можете прочитать мой pull request для перехода на Observation в репозитории Ice Cubes здесь.
Производительность SwiftUI
Два момента, касающихся производительности SwiftUI:
- При компиляции в Xcode 15/iOS 17 SDK приложение работает гораздо быстрее на устройствах с iOS 16 и 17. Вероятно, это связано с другой версией библиотеки SwiftUI, и Apple, похоже, значительно улучшила производительность. Но это действительно заметно на Ice Cubes. Пользователи хвалят скорость работы приложения после последнего обновления (это было первое обновление, которое я отправил с Xcode 15 RC).
- Перенос приложения на фреймворк Observation сделал его еще быстрее. И в этом есть смысл. Временная шкала в Ice Cubes — один из самых сложных видов иерархии приложения. Она отображает статусы с большим количеством данных, которыми можно манипулировать, учитывая различные настройки пользователей. Строка состоит из различных небольших представлений, но имеет массу зависимостей от различных значений окружения.
![]()
При профилировании приложения прокрутка таймлайна сейчас вызывает гораздо меньше обновлений свойств и представлений, благодаря тому, что Observable умнее определяет, когда обновлять представление, например, при изменении свойства в модели представления.
![]()
И еще одно: не забывайте использовать @ObservationIgnored, если вы не хотите, чтобы представление реагировало на изменение конкретного свойства. Если до этого у вас не было обертки свойства @Published, то, вероятно, это хороший кандидат, чтобы сделать это. Это означает, что оно не будет вызывать обновления представления, даже если вы используете его в теле представления.
@MainActor
@Observable class StatusDetailViewModel {
enum State {
case loading, display(statuses: [Status]), error(error: Error)
}
var state: State = .loading
@ObservationIgnored
var isReplyToPreviousCache: [String: Bool] = [:]
}
После преобразования ObservableObject в @Observable представление, отвечающее за хранение объекта, должно использовать @State (вместо @StateObject), но при простой передаче объекта в одно из вложенных представлений никакой специальной аннотации не требуется.
public struct StatusRowView: View {
@State private var viewModel: StatusRowViewModel
public init(viewModel: StatusRowViewModel) {
_viewModel = .init(initialValue: viewModel)
}
public var body: some View {
HStack(spacing: 0) {
...
StatusRowContentView(viewModel: viewModel)
}
}
struct StatusRowContentView: View {
var viewModel: StatusRowViewModel
var body: some View {
if !viewModel.finalStatus.spoilerText.asRawText.isEmpty {
@Bindable var viewModel = viewModel
StatusRowSpoilerView(status: viewModel.finalStatus, displaySpoiler: $viewModel.displaySpoiler)
}
}
Например, выше показано одно из вложенных представлений моего StatusRowView, на viewModel ссылаются как на простую переменную, и представление все равно будет реагировать на любое изменение свойства, используемого в теле этого представления.
Затем, если вам нужно передать свойство этого объекта в качестве привязки другому представлению, вы можете сделать свой объект Bindable в конструкторе представлений.
Мне пока больше нечего сказать. Фреймворк Observation — это огромное улучшение для SwiftUI. Он прост и избавляет от головной боли по сравнению с предыдущим потоком данных. «Это просто работает», как сказал бы Тодд Говард 🚀.
-
Разработка2 недели назадДаем ИИ видеть SwiftUI: Xcode Preview MCP на практике — проблемы и надежды
-
Новости3 недели назадВидео и подкасты о мобильной разработке 2026.39
-
Новости4 недели назадВидео и подкасты о мобильной разработке 2026.38
-
Новости2 недели назадВидео и подкасты о мобильной разработке 2026.40
