Какие способы оптимизации производительности в SwiftUI существуют
Что проверяют
Понимаете ли вы, как SwiftUI решает, что пересчитать: идентичность view, зависимости body и стоимость самого body. Следом обычно просят показать, как вы нашли лишнюю перерисовку на практике.
Как отвечать
Сначала механика: SwiftUI заново вызывает body у view, чьи зависимости изменились, и сравнивает результат. Отсюда приёмы:
- узкие зависимости:
ObservableObjectоповещает всех подписчиков при изменении любого@Published, а макрос@Observable(Observation, iOS 17+) отслеживает только свойства, реально прочитанные вbody. В дочерний view передавайте нужные значения, а не всю модель; - мелкие подвью: большой
bodyразбивается на отдельные структуры, тогда инвалидация остаётся локальной; - дешёвый
body: никакихDateFormatter, сортировок и фильтров внутри, всё это считается в модели заранее; - стабильная идентичность: у
ForEachпостоянныйidиз данных, а не индекс. Веткаif/elseсоздаёт разные view и сбрасывает состояние, часто лучше менять значение модификатора; - без
AnyView: стирание типа мешает сравнению, вместо него@ViewBuilderили дженерики; - ленивые контейнеры:
LazyVStack,LazyVGridилиListвместоVStackвScrollViewна сотни строк; - точечные инструменты:
.equatable()для view с дорогим сравнением,.taskдля загрузки с автоматической отменой,drawingGroup()для сложной векторной графики; - картинки: декодировать и уменьшать до размера на экране, у
AsyncImageнет собственного кэша в памяти.
Диагностика: let _ = Self._printChanges() внутри body печатает причину пересчёта, шаблон SwiftUI в Instruments и Time Profiler показывают долгие обновления.
Где спотыкаются
Складывают всё состояние экрана в один @EnvironmentObject. Любая мелочь в нём перерисовывает весь экран.
Пишут .id(UUID()) или генерируют id в ForEach на лету. SwiftUI каждый раз видит новый view, сбрасывает его состояние и анимации.
Лечат вслепую: навешивают EquatableView и рассказывают, что @ViewBuilder будто бы «предкомпилирует» view. На деле он лишь собирает несколько view в одно значение, а эффект любой правки без замера Release-сборки на устройстве не доказать.