← Назад к вопросам

Что такое @State, @Binding, @ObservedObject и @EnvironmentObject в SwiftUI?

1.3 Junior🔥 211 комментариев
#CI/CD и инструменты разработки#Soft Skills и карьера#SwiftUI

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Сводка по property wrappers SwiftUI

В SwiftUI property wrappers — это фундаментальный механизм управления состоянием и потоком данных. Они позволяют декларативно описывать зависимости между интерфейсом и данными, автоматически обновляя представления при изменении значений.

@State

@State используется для хранения приватного состояния, принадлежащего конкретному представлению. SwiftUI управляет хранилищем этого состояния и пересоздает его при уничтожении представления.

  • Применяется только к value-типам (структурам, строкам, числам, перечислениям).
  • Модифицировать можно только внутри представления (с модификатором private).
  • Изменение значения вызывает перерисовку представления.
struct CounterView: View {
    @State private var count = 0 // Локальное состояние
    
    var body: some View {
        VStack {
            Text("Счёт: \(count)")
            Button("Увеличить") {
                count += 1 // Прямое изменение
            }
        }
    }
}

@Binding

@Binding создаёт двустороннюю связь с состоянием, принадлежащим другому представлению. Это позволяет передавать состояние «вниз» по иерархии представлений без явной передачи замыканий для обновления.

  • Не хранит данные, а лишь ссылается на источник (часто на @State).
  • Используется для создания дочерних компонентов, которые должны читать и записывать значение родителя.
struct ParentView: View {
    @State private var isOn = false
    
    var body: some View {
        VStack {
            Text("Состояние: \(isOn ? "Вкл" : "Выкл")")
            ToggleView(isOn: $isOn) // Передаём Binding
        }
    }
}

struct ToggleView: View {
    @Binding var isOn: Bool // Принимаем Binding
    
    var body: some View {
        Toggle("Переключатель", isOn: $isOn)
    }
}

@ObservedObject

@ObservedObject используется для отслеживания изменений во внешнем объекте, соответствующем протоколу ObservableObject. Этот объект живёт вне представления и управляется извне.

  • Объект должен быть reference-типом (классом).
  • Источником изменений является @Published свойства или явный вызов objectWillChange.send().
  • При изменении объекта SwiftUI перерисовывает представление.
class UserSettings: ObservableObject {
    @Published var username = "Гость" // Изменения публикуются
}

struct ProfileView: View {
    @ObservedObject var settings: UserSettings // Наблюдаемый объект
    
    var body: some View {
        TextField("Имя пользователя", text: $settings.username)
    }
}

@EnvironmentObject

@EnvironmentObject предоставляет доступ к общим данным, которые автоматически передаются через всю иерархию представлений. Это аналог «контекста» или «глобального состояния» в рамках определенного дерева View.

  • Объект должен соответствовать ObservableObject.
  • Не требует явной передачи через инициализаторы промежуточных представлений.
  • Представление крашится, если объект не передан в environmentObject().
class AppState: ObservableObject {
    @Published var isLoggedIn = false
}

@main
struct MyApp: App {
    @StateObject private var appState = AppState()
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(appState) // Инжектим в среду
        }
    }
}

struct ContentView: View {
    @EnvironmentObject var appState: AppState // Получаем из среды
    
    var body: some View {
        VStack {
            if appState.isLoggedIn {
                Text("Добро пожаловать!")
            } else {
                LoginView()
            }
        }
    }
}

Ключевые отличия и рекомендации по использованию

WrapperВладение даннымиТип данныхОбласть видимостиИспользование
@StateПредставлениеValue-типыЛокальное в ViewПростое состояние внутри компонента
@BindingСсылка на источникЛюбой (обычно Binding)Дочерние ViewДвусторонняя связь с родителем
@ObservedObjectВнешний источникКласс (ObservableObject)Конкретное представлениеСложное состояние, разделяемое между несколькими View
@EnvironmentObjectГлобальный источникКласс (ObservableObject)Вся иерархия ViewОбщедоступные данные (авторизация, настройки)

Важные принципы:

  • Для ObservableObject в iOS 14+ используйте @StateObject в месте создания, чтобы гарантировать жизненный цикл.
  • @ObservedObject и @EnvironmentObject только подписываются на изменения, но не владеют объектом.
  • Избегайте избыточного использования @EnvironmentObject для данных, которые нужны лишь нескольким соседним представлениям — лучше передать через @ObservedObject.

Эти property wrappers формируют реактивную систему SwiftUI, где интерфейс автоматически синхронизируется с данными, уменьшая boilerplate-код и предотвращая распространённые ошибки управления состоянием.

Что такое @State, @Binding, @ObservedObject и @EnvironmentObject в SwiftUI? | PrepBro