@State — o que é, propósito e uso em SwiftUI

Autor: IT Sectr Publicado: 2026-06-19 Tempo de leitura: 7 min

@State é um Property Wrapper em SwiftUI para gerenciar estado local dentro de uma única view. O SwiftUI redesenha automaticamente a view sempre que uma propriedade @State muda, tornando a interface reativa sem chamadas manuais de atualização. De acordo com a Apple Developer Documentation (2025), @State é recomendado para tipos simples e estruturas pertencentes a uma única view. @State é a maneira mais simples de adicionar interatividade a uma interface SwiftUI.

Principais pontos

  • @State — Property Wrapper para estado local pertencente a uma única view
  • Atualização automática — SwiftUI reinvoca body quando uma propriedade @State muda
  • Tipos simples — @State funciona com String, Int, Bool, enum e structs
  • Não passar para views filhas — use @Binding para alterações de componentes filhos
  • private — propriedades @State são sempre declaradas com o modificador private

O que é @State no SwiftUI?

@State é um Property Wrapper integrado ao SwiftUI que permite que uma view armazene e monitore seu próprio estado. Quando um valor @State muda, o SwiftUI redesenha automaticamente a view reinvocando a propriedade body. Esta é a base da programação reativa no SwiftUI: o desenvolvedor declara o estado e o framework cuida da sincronização da interface.

@State cria uma área de armazenamento no heap gerenciada pelo SwiftUI. Esta área é persistente — ela sobrevive a inicializações repetidas da estrutura da view, que ocorrem a cada renderização. O SwiftUI usa o identificador da view (gerado a partir de sua posição na hierarquia) para vincular a propriedade @State a uma view específica. Graças a isso, o estado não é redefinido quando a view pai é atualizada.

Uma limitação importante: @State é destinado apenas a tipos de valor (structs, enums, primitivos). Para tipos de referência (classes), use @StateObject ou @ObservedObject. Se você atribuir uma classe a uma propriedade @State, o SwiftUI não conseguirá detectar alterações dentro do objeto — apenas a substituição completa da referência.

Como @State funciona internamente?

O SwiftUI implementa @State por meio de um mecanismo interno de Storage. Cada propriedade @State recebe uma célula de memória dedicada armazenada em um contêiner de armazenamento especial da view. Quando ocorre uma escrita em wrappedValue, o SwiftUI notifica seu grafo de dependências via didSet sobre a necessidade de redesenhar.

swift
struct ContentView: View {
    @State private var name: String = "User"
    @State private var isLoggedIn: Bool = false

    var body: some View {
        VStack {
            Text("Olá, \(name)")
            Button(isLoggedIn ? "Sair" : "Entrar") {
                isLoggedIn.toggle()
            }
        }
    }
}

No exemplo, há duas propriedades @State: name (String) e isLoggedIn (Bool). Quando isLoggedIn.toggle() é chamado, o SwiftUI marca ContentView como precisando de atualização e reinvoca body no próximo ciclo de renderização. O ponto-chave: propriedades @State são sempre declaradas com o modificador private — isso sinaliza que o estado pertence exclusivamente à view atual e não deve ser alterado externamente diretamente.

Para observar mudanças, o SwiftUI usa CurrentValueSubject do Combine. Cada propriedade @State cria um publisher oculto que notifica o sistema a cada alteração. Isso permite que o SwiftUI redesenhe apenas o conjunto mínimo necessário de views, evitando atualizações completas da hierarquia.

Quando usar @State em um projeto

@State é ideal para estados locais simples: campos de texto em pesquisa, flags booleanas para janelas modais, alternâncias de configuração, contadores, itens de lista selecionados. Se um valor é usado apenas em uma view e seus componentes filhos (via @Binding), @State é a escolha certa. Para estados que devem sobreviver ao fechamento da view (por exemplo, dados de formulário), @State também funciona enquanto a view permanecer na hierarquia.

  • Campos de texto — @State para armazenar texto inserido em TextField
  • Flags booleanas — @State para mostrar/esconder janelas modais e sheets
  • Seleção de elementos — @State para rastrear a aba ou linha selecionada
  • Contadores — @State para valores numéricos com incremento/decremento
  • Cálculos intermediários — @State para armazenar em cache resultados dentro de uma view

Não use @State para estados globais da aplicação, cache de dados de rede ou objetos usados em várias telas. @StateObject e @EnvironmentObject são projetados para esses fins. Além disso, @State não é adequado para armazenar grandes quantidades de dados — cada alteração redesenhará a view inteira.

@State e @Binding: trabalhando juntos

@Binding é uma ponte entre @State em uma view pai e uma view filha que precisa modificar esse estado. O pai declara @State, e o componente filho recebe um Binding por meio da projeção $. Alterar o Binding na view filha atualiza automaticamente o @State no pai — e vice-versa. Isso garante um fluxo de dados unidirecional com capacidade de feedback.

swift
struct ParentView: View {
    @State private var text: String = ""

    var body: some View {
        ChildView(text: $text)
    }
}

struct ChildView: View {
    @Binding var text: String

    var body: some View {
        TextField("Enter text", text: $text)
    }
}

Na listagem, ParentView possui o @State text, e ChildView recebe $text como Binding. O TextField dentro de ChildView se vincula a este Binding via text: $text. Quando o usuário digita no TextField, o valor muda em ChildView através do Binding, o que causa uma atualização de @State em ParentView. Ambas as views são redesenhadas com o novo valor.

Erros comuns ao trabalhar com @State

O erro mais comum é atribuir uma classe a uma propriedade @State. Se você escrever @State var model = MyClass(), o SwiftUI não conseguirá rastrear alterações nas propriedades dentro da classe — apenas a substituição do objeto. Para classes, sempre use @StateObject. O segundo problema comum é declarar @State sem o modificador private, o que viola o princípio de encapsulamento do estado.

Passar @State diretamente para uma view filha sem $ é outro erro típico. Se você passar TextField(text: text) em vez de TextField(text: $text), o componente filho receberá apenas uma string, não um Binding. As alterações de texto no TextField não serão sincronizadas com o @State do pai. Sempre use a projeção $ para passar Binding.

O terceiro erro são múltiplas propriedades @State para dados relacionados. Se vários valores formam logicamente um todo único (por exemplo, campos de formulário), combine-os em uma única estrutura com um único @State. Isso simplifica a passagem de estado para views filhas e reduz o número de gatilhos de atualização individuais.

Exemplos de uso de @State no SwiftUI

@State é usado na maioria dos projetos SwiftUI para interatividade básica. Considere um exemplo de formulário de login onde @State gerencia campos de texto e estado de carregamento. Esse padrão aparece em todos os aplicativos — desde notas simples até soluções empresariais complexas.

swift
struct LoginView: View {
    @State private var email: String = ""
    @State private var password: String = ""
    @State private var isLoading: Bool = false
    @State private var errorMessage: String?

    var body: some View {
        Form {
            TextField("Email", text: $email)
            SecureField("Password", text: $password)
            Button("Entrar") {
                login()
            }.disabled(isLoading)
        }
    }

    private func login() {
        isLoading = true
        // Realizar requisição de rede
    }
}

No exemplo, há quatro propriedades @State: email e password para os campos do formulário, isLoading para indicação de carregamento e errorMessage para exibir erros. Cada propriedade gerencia independentemente sua parte da interface. Quando isLoading muda, o botão é automaticamente desabilitado via disabled(isLoading) — sem atualização manual da UI.

Perguntas frequentes

Por que @State é declarado com private?

@State é projetado para o estado local de uma view específica. O modificador private garante que outros componentes não possam alterá-lo diretamente, quebrando o encapsulamento. Para acesso externo, use a projeção $.

@State pode conter um array ou dicionário?

Sim, @State suporta arrays e dicionários, pois são tipos de valor. No entanto, quando um elemento de um array muda, o SwiftUI redesenha a view inteira. Para listas grandes, @StateObject com @Published é mais eficiente.

O que acontece quando nil é atribuído a uma propriedade @State com tipo Optional?

@State funciona corretamente com tipos Optional. Quando nil é atribuído, o SwiftUI detecta a mudança e redesenha a view. Isso é conveniente para estados como errorMessage: String?, onde nil significa nenhum erro.

Como @State se comporta quando a view reaparece?

@State preserva o valor enquanto a view permanecer na hierarquia. Se a view for removida da hierarquia e adicionada novamente, @State é reinicializado com o valor padrão. Para persistência, use @AppStorage.

As alterações de @State podem ser animadas?

Sim, envolva a alteração em withAnimation: withAnimation(.easeInOut) { isExpanded.toggle() }. O SwiftUI anima a transição entre o estado antigo e o novo da interface com o tipo de animação especificado.

Resumo

  • @State — Property Wrapper para estado local de uma única view, atualizando automaticamente a interface
  • Funciona com tipos simples: String, Int, Bool, além de structs e enums
  • Não funciona com tipos de referência (classes) — use @StateObject
  • Sempre private — o estado não deve ser alterado externamente diretamente
  • Projeção $ — cria um Binding para passar direitos de alteração para views filhas
  • Múltiplos @State em uma view — prática normal para estados independentes
  • withAnimation — permite animar alterações em propriedades @State

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