Что такое environment в SwiftUI и как его настроить?

Ответ

Environment (окружение) в SwiftUI — это механизм для передачи зависимостей (данных, объектов, значений) через иерархию представлений без явной передачи через инициализаторы каждого view.

Основные инструменты:

  • @Environment — для чтения системных или кастомных значений.
  • @EnvironmentObject — для передачи ссылочных типов (ObservableObject).
  • Модификатор .environment() — для установки значений.

Как создать и использовать кастомное environment-значение:

  1. Определите ключ:
    struct ThemeKey: EnvironmentKey {
    static let defaultValue: Color = .blue // Значение по умолчанию
    }
  2. Расширьте EnvironmentValues:
    extension EnvironmentValues {
    var theme: Color {
        get { self[ThemeKey.self] }
        set { self[ThemeKey.self] = newValue }
    }
    }
  3. Используйте в дочернем view:

    struct ContentView: View {
    @Environment(.theme) var theme // Чтение значения
    
    var body: some View {
        Text("Hello")
            .foregroundColor(theme)
    }
    }
  4. Установите значение в родительском view:
    ParentView()
    .environment(.theme, .red) // Установка значения

    Ключевое отличие от @EnvironmentObject: @Environment работает с value-типами и системными настройками (размер шрифта, locale), а @EnvironmentObject — для общих моделей данных (ObservableObject).

Ответ 18+ 🔞

Слушай, а вот эта ваша штука — Environment в SwiftUI. Ну, в натуре, механизм, чтобы не таскать данные через всю иерархию, как чемодан без ручки, понимаешь? Сука, блядь, чтобы не прокидывать каждому вьюхе в инициализатор, как какую-то сволочь, через десять родителей.

Основные инструменты, на которые можно опереться, пока не упал:

  • @Environment — это чтобы почитать какие-то системные или свои собственные, блядь, значения. Как будто из воздуха достать.
  • @EnvironmentObject — это уже для тяжёлой артиллерии, для этих ваших ObservableObject, ссылочных типов, которые везде нужны.
  • Модификатор .environment() — это волшебная палочка, которой ты, сука, это самое значение в воздух и засовываешь.

Как сварганить своё собственное environment-значение, чтобы все ахнули:

  1. Выдумай ключ, ёпта:
    struct ThemeKey: EnvironmentKey {
    static let defaultValue: Color = .blue // Значение по умолчанию, если сверху нихуя не положили
    }
  2. Расширь EnvironmentValues, как тётя Клава расширяет свою юбку после праздников:
    extension EnvironmentValues {
    var theme: Color {
        get { self[ThemeKey.self] } // Достаём
        set { self[ThemeKey.self] = newValue } // Кладём
    }
    }
  3. Используй в дочернем вью, как будто так и надо:

    struct ContentView: View {
    @Environment(.theme) var theme // Просто взял и прочитал, блядь, из ниоткуда
    
    var body: some View {
        Text("Hello")
            .foregroundColor(theme) // И раскрасил им текст, красота ёбта!
    }
    }
  4. А теперь, сука, установи это значение где-то наверху, в родительском вью:
    ParentView()
    .environment(.theme, .red) // Всё, теперь всё ниже по течению будет красным, пиздец!

А теперь главное, блядь, отличие от @EnvironmentObject, чтобы в голове не путалось:
@Environment — это больше для value-типов (как Color) или системных настроек (типа размер шрифта, locale, эта вся хуйня). А @EnvironmentObject — это когда у тебя целая модель данных, ObservableObject, которая должна быть доступна всем, как водка на празднике. Первое — как передать флажок, второе — как передать целый бар с бухлом.