Ответ
Оба метода передают данные вниз по иерархии представлений SwiftUI, но предназначены для разных типов данных и имеют разные правила использования.
@Environment и .environment(_:value:)
Используется для передачи значений, соответствующих заранее определенным ключам (EnvironmentKey). Часто это системные настройки или собственные контекстные значения.
Пример: Чтение системного значения и установка своего:
// 1. Определение своего ключа окружения
struct ThemeKey: EnvironmentKey {
static let defaultValue = Color.blue
}
extension EnvironmentValues {
var customTheme: Color {
get { self[ThemeKey.self] }
set { self[ThemeKey.self] = newValue }
}
}
// 2. Установка значения с помощью .environment
ContentView()
.environment(.customTheme, .green) // Устанавливаем свое значение
.environment(.colorScheme, .dark) // Устанавливаем системное значение
// 3. Чтение значения в дочернем виде
struct ChildView: View {
@Environment(.customTheme) var themeColor
@Environment(.colorScheme) var colorScheme // Системное
var body: some View {
Text("Hello")
.foregroundColor(themeColor)
}
}
@EnvironmentObject и .environmentObject(_:)
Используется для передачи экземпляра класса, соответствующего протоколу ObservableObject. Предназначен для разделяемых моделей данных, которые могут изменяться и вызывать обновление UI.
Пример:
// 1. ObservableObject класс модели
class UserSettings: ObservableObject {
@Published var username = "Alex"
}
// 2. Создание и внедрение объекта в корне иерархии
@main
struct MyApp: App {
@StateObject var settings = UserSettings() // Владение
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(settings) // Передача вниз
}
}
}
// 3. Получение и использование в любом дочернем виде
struct ProfileView: View {
@EnvironmentObject var settings: UserSettings // Не требует инициализации
var body: some View {
TextField("Name", text: $settings.username)
}
}
| Сводка отличий: | Признак | @Environment / .environment() | @EnvironmentObject / .environmentObject() |
|---|---|---|---|
| Тип данных | Любое значение (Value-type) | Только ссылочный тип, реализующий ObservableObject |
|
| Ключ | Требуется предопределенный EnvironmentKey |
Используется тип самого объекта в качестве ключа | |
| Использование | Системные настройки (.colorScheme), темы, флаги |
Разделяемые модели данных (UserSettings, AppState) | |
| Безопасность | Имеет defaultValue, всегда возвращает значение |
Вызовет краш, если объект не был передан до использования | |
| Обновление UI | Обновляет вид, только если значение изменилось (Hashable) | Автоматически обновляет вид при изменении @Published свойств |