@Environment em SwiftUI — o que é, conceitos-chave e mecanismo

Autor: IT Sectr Publicado: 2026-06-25 Tempo de leitura: 8 min

@Environment no SwiftUI é um property wrapper para ler valores do ambiente do sistema, distribuídos automaticamente pela hierarquia de Views. O componente fornece acesso ao esquema de cores, localidade, tamanho da fonte, managedObjectContext e dezenas de outros parâmetros do sistema. De acordo com a Documentação Apple Developer (2025), @Environment garante que qualquer alteração em um valor do ambiente cause uma redraw de todas as Views inscritas, fornecendo atualizações reativas da interface sem chamadas manuais.

Principais pontos

  • @Environment — um property wrapper para ler valores do ambiente do sistema SwiftUI
  • Esquema de cores, localidade e tamanho da fonte são valores do sistema comuns
  • Alterar qualquer valor do ambiente causa redraw automático das Views inscritas
  • Chaves personalizadas permitem criar seus próprios valores de ambiente via EnvironmentKey
  • @Environment — somente leitura; @EnvironmentObject — para escrita

O que é @Environment no SwiftUI?

@Environment é um property wrapper do SwiftUI projetado para ler valores do ambiente do sistema. O ambiente é um contêiner hierárquico de valores que o SwiftUI distribui automaticamente das Views pai para as Views filhas. Cada valor do ambiente é identificado por uma chave — um tipo que segue o protocolo EnvironmentKey.

O mecanismo de ambiente se assemelha à injeção de dependência no nível do framework: o sistema fornece um conjunto predefinido de valores — esquema de cores (claro/escuro), localidade, tamanho da fonte, managedObjectContext para Core Data, dismiss para fechar telas, e muitos outros. Uma View que declara @Environment com uma chave específica recebe automaticamente o valor atual e é redesenhada quando ele muda.

A arquitetura do ambiente SwiftUI é baseada no protocolo EnvironmentValues — uma estrutura contendo todos os valores do sistema. Cada valor é armazenado como uma propriedade desta estrutura com getter e setter. @Environment usa um key path para acessar uma propriedade específica: @Environment(\.colorScheme) — acesso ao esquema de cores, @Environment(\.locale) — acesso à localidade.

@Environment como Property Wrapper

O property wrapper @Environment implementa dois mecanismos principais: ler um valor do ambiente e se inscrever em suas alterações. Quando uma View é criada, o SwiftUI percorre todas as propriedades @Environment e as vincula aos valores correspondentes do contexto atual. Se uma View pai altera um valor através do modificador .environment(), todas as Views filhas que leem esse valor são automaticamente redesenhadas.

Uma característica importante: @Environment suporta valores opcionais. Se um valor não estiver definido na hierarquia, o valor padrão definido em EnvironmentKey é retornado. Para chaves do sistema, o valor padrão é sempre razoável — por exemplo, o esquema de cores padrão é .light. Para chaves personalizadas, o desenvolvedor define o valor padrão no método defaultValue do protocolo EnvironmentKey.

swift
struct EnvironmentReaderView: View {
    @Environment(\.colorScheme) var colorScheme
    @Environment(\.locale) var locale
    @Environment(\.sizeCategory) var sizeCategory

    var body: some View {
        VStack {
            Text("Current scheme: \(colorScheme == .dark ? "Dark" : "Light")")
            Text("Locale: \(locale.identifier)")
            Text("Font size: \(sizeCategory)")
        }
    }
}

No exemplo, a View lê três valores do ambiente do sistema. Quando colorScheme muda — por exemplo, o usuário ativou o modo escuro nas configurações — a View é automaticamente redesenhada com o novo valor. Da mesma forma quando a região ou o tamanho da fonte (Dynamic Type) mudam. A View não precisa se inscrever em notificações ou chamar refresh — o SwiftUI gerencia isso automaticamente.

Valores do ambiente do sistema

O SwiftUI fornece dezenas de valores do ambiente do sistema cobrindo vários aspectos da interface e comportamento. Esquema de cores (\.colorScheme) é um dos valores mais usados, permitindo adaptar a interface aos temas claro e escuro. Localidade (\.locale) contém as configurações regionais do usuário para formatar datas, números e moedas.

Para Core Data, managedObjectContext (\.managedObjectContext) é usado — um contexto passado através do ambiente do container de persistência. Para navegação, estão disponíveis dismiss (\.dismiss) para fechar a tela atual e isPresented (\.isPresented) para apresentações modais. Para calendário e fuso horário — calendar e timeZone respectivamente.

Key PathTipoPropósito
\.colorSchemeColorSchemeTema claro ou escuro
\.localeLocaleConfigurações regionais
\.sizeCategoryContentSizeCategoryTamanho da fonte Dynamic Type
\.managedObjectContextNSManagedObjectContextContexto Core Data
\.dismissDismissActionFechar tela
\.calendarCalendarCalendário atual
\.timeZoneTimeZoneFuso horário
\.horizontalSizeClassUserInterfaceSizeClassTamanho horizontal da tela

Para acessar valores do sistema, use o key path com um ponto: @Environment(\.dismiss) var dismiss. O compilador verifica a existência do key path em EnvironmentValues, portanto uma chave incorreta causará um erro em tempo de compilação. A Apple adiciona novos valores do sistema a cada versão do iOS — a lista completa está disponível na documentação EnvironmentValues.

@Environment vs @EnvironmentObject

Apesar dos nomes semelhantes, @Environment e @EnvironmentObject têm propósitos diferentes. @Environment lê valores do sistema ou personalizados registrados através de EnvironmentKey. @EnvironmentObject é um property wrapper para um ObservableObject passado pelo ambiente por tipo, sem uma chave explícita.

@EnvironmentObject é usado para injeção de dependência: uma View pai cria um objeto (por exemplo, ViewModel) e o passa para Views filhas através do modificador .environmentObject(). As Views filhas o recebem através de @EnvironmentObject e podem ler e modificar suas propriedades. @Environment, por outro lado, é somente leitura para valores do sistema e não suporta feedback.

Parâmetro@Environment@EnvironmentObject
PropósitoValores do sistema e personalizadosInjeção ObservableObject
ChaveKey path EnvironmentValuesPor tipo do objeto
EscritaSomente leituraLeitura e escrita
Valor personalizadoAtravés de EnvironmentKeyAtravés de classe ObservableObject
Valor padrãoSim (defaultValue)Não (deve ser passado)

Na prática: use @Environment para acessar parâmetros do sistema (tema, localidade, tamanho da fonte) e configurações personalizadas que não mudam em tempo de execução. Use @EnvironmentObject para passar um ViewModel ou serviço pela hierarquia de Views quando o estado precisar ser modificado a partir de componentes filhos.

Exemplos de código @Environment

Vamos ver a criação de um valor de ambiente personalizado. Para isso, você precisa definir uma estrutura que siga o protocolo EnvironmentKey e estender EnvironmentValues com uma nova propriedade. Isso permite passar configuração de tema ou ajustes do aplicativo por toda a árvore de Views sem props.

swift
struct AppThemeKey: EnvironmentKey {
    static let defaultValue: AppTheme = .system
}

extension EnvironmentValues {
    var appTheme: AppTheme {
        get { self[AppThemeKey.self] }
        set { self[AppThemeKey.self] = newValue }
    }
}

enum AppTheme { case system, light, dark }

O protocolo EnvironmentKey exige a implementação da propriedade estática defaultValue — o valor que será usado se a View pai não tiver definido um ambiente personalizado. Estender EnvironmentValues adiciona uma propriedade calculada appTheme usando um subscript com a chave. Depois disso, qualquer View pode ler o valor através de @Environment(\.appTheme).

Usando @Environment com uma chave personalizada

swift
struct ThemedView: View {
    @Environment(\.appTheme) var appTheme
    @Environment(\.colorScheme) var colorScheme

    var body: some View {
        VStack {
            if appTheme == .dark || (appTheme == .system && colorScheme == .dark) {
                Text("Dark mode active")
                    .foregroundStyle(.white)
                    .background(Color.black)
            } else {
                Text("Light mode active")
                    .foregroundStyle(.black)
                    .background(Color.white)
            }
        }
    }
}

struct ContentView: View {
    @State private var selectedTheme = AppTheme.system

    var body: some View {
        ThemedView()
            .environment(\.appTheme, selectedTheme)
    }
}

ThemedView lê dois ambientes: o personalizado appTheme e o do sistema colorScheme. A combinação permite configuração flexível de tema: o usuário pode escolher o tema Claro, Escuro ou Sistema. Se Sistema for selecionado, o valor é obtido de colorScheme, que muda automaticamente ao alternar o tema nas configurações do iOS. A View pai (ContentView) define o valor de appTheme através do modificador .environment().

Usando dismiss para fechar uma tela

swift
struct ModalView: View {
    @Environment(\.dismiss) var dismiss
    @State private var name = ""

    var body: some View {
        NavigationStack {
            Form {
                TextField("Your name", text: $name)
                Button("Save") { dismiss() }
            }
            .navigationTitle("Edit Profile")
        }
    }
}

Este exemplo demonstra o uso prático de dismiss — uma instância de DismissAction do ambiente. Chamar dismiss() como uma função fecha a tela modal ou volta o NavigationLink. O único requisito é que a View seja apresentada modalmente ou esteja dentro de um NavigationStack. dismiss é determinado automaticamente pelo contexto: se a View foi aberta como sheet — a sheet é fechada, se como popover — o popover é fechado.

Perguntas frequentes

Posso alterar um valor @Environment de uma View filha?

Não, @Environment é somente leitura. Para alterar valores, use @EnvironmentObject com ObservableObject ou @Binding. EnvironmentKeys personalizados podem ter um setter na extensão, mas alterar através dele não dispara atualizações de interface — isso é tecnicamente possível mas não recomendado.

Qual a diferença entre @Environment e @Binding?

@Binding cria uma conexão bidirecional com uma fonte da verdade (State, StateObject, ObservableObject). @Environment é uma leitura unidirecional do contexto hierárquico. @Binding é adequado para passar dados para uma View filha, @Environment — para acessar configurações do sistema ou globais.

Como criar meu próprio valor de ambiente?

Defina uma estrutura que implemente o protocolo EnvironmentKey com um defaultValue estático. Depois estenda EnvironmentValues com uma propriedade usando getter/setter via subscript[key]. Após o registro, use @Environment(\.yourKey) para ler e .environment(\.yourKey, value) para definir.

Quais valores de ambiente estão disponíveis no SwiftUI?

SwiftUI fornece mais de 50 valores do sistema: colorScheme, locale, sizeCategory, managedObjectContext, dismiss, calendar, timeZone, horizontalSizeClass, verticalSizeClass, accessibilityEnabled, layoutDirection, legibilityWeight e outros. Lista completa na documentação EnvironmentValues.

O @Environment funciona no Preview?

Sim, @Environment funciona no Preview, mas os valores padrão podem diferir do simulador. Para testar no Preview, use o modificador .environment() diretamente no código Preview: ThemedView().environment(\.colorScheme, .dark). Isso permite verificar visualmente diferentes estados do ambiente.

Resumo

  • @Environment — um property wrapper para ler valores do ambiente do sistema SwiftUI via key path
  • Esquema de cores, localidade, tamanho da fonte e managedObjectContext são os valores do sistema mais usados
  • Alterar um valor do ambiente causa redraw automático de todas as Views inscritas
  • EnvironmentKey personalizado permite estender o ambiente do aplicativo com configurações globais
  • @Environment — somente leitura; @EnvironmentObject — para ObservableObject com acesso de escrita
  • O modificador .environment() define um valor para Views filhas na hierarquia
  • Use @Environment para parâmetros do sistema, @EnvironmentObject — para ViewModel e serviços

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também