Для чего используется @State в SwiftUI?
Что проверяют
Понимаете ли вы, кому принадлежит состояние в SwiftUI и почему значение переживает пересоздание структуры View. Следом почти всегда просят сравнить @State с @Binding, @StateObject и @Observable.
Как отвечать
@State это обёртка свойства для локального состояния, которым владеет сама вью.
- хранение: структура
Viewпересоздаётся при каждом обновлении родителя, но значение@Stateлежит не в ней, а в хранилище SwiftUI, привязанном к идентичности вью в иерархии. Пока идентичность та же, значение сохраняется; - перерисовка: изменение значения инвалидирует
bodyвью, которая его читает, и SwiftUI пересчитывает её; private: Apple рекомендует писать@State private var, потому что состояние внутреннее и снаружи задаваться не должно;$-проекция:$isOnдаётBinding, который передают дочерней вью с@Binding. Владелец один, остальные читают и пишут через привязку;- ссылочные типы: с iOS 17 и фреймворком Observation в
@Stateхранят и класс с макросом@Observable, для новых проектов это замена@StateObject.
Подходит для простого UI-состояния: флаг показа шита, текст поля, выбранная вкладка. Данные, нужные нескольким экранам, живут в модели уровнем выше.
Где спотыкаются
Инициализируют @State из параметра родителя и ждут, что он будет обновляться. Начальное значение применяется один раз, когда вью появилась в иерархии, дальнейшие изменения параметра игнорируются. Для данных сверху нужен обычный let или @Binding.
Кладут в @State класс, реализующий ObservableObject. Изменения его @Published-свойств не вызовут перерисовку: @State замечает только замену самой ссылки. Для такого класса нужен @StateObject, а с @Observable отслеживание работает.
Не учитывают, что @State private var model = Model() вызывает инициализатор при каждом создании структуры вью. SwiftUI оставит первый экземпляр, но если init у модели тяжёлый, лишние вызовы обходятся дорого. Тяжёлую подготовку переносят в .task.