@AppStorage no SwiftUI — o que é, UserDefaults e armazenamento de configurações

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

@AppStorage no SwiftUI é um property wrapper para trabalhar com UserDefaults que sincroniza automaticamente o valor com a UI. Quando uma propriedade declarada com @AppStorage muda, o novo valor é imediatamente salvo em UserDefaults, e quando UserDefaults muda externamente — por um widget ou extensão — a View é redesenhada automaticamente. De acordo com Apple Developer Documentation (2025), @AppStorage suporta String, Int, Double, Bool, Data, URL e suas versões opcionais, fornecendo armazenamento reativo de configurações do usuário sem código de observação manual.

Principais Pontos

  • @AppStorage — property wrapper para trabalho reativo com UserDefaults no SwiftUI
  • Auto-salvamento — o valor é escrito em UserDefaults a cada mudança
  • Auto-atualização da UI — a View é redesenhada quando UserDefaults muda de qualquer fonte
  • Tipos suportados: String, Int, Double, Bool, Data, URL e versões opcionais
  • Valor padrão é definido na declaração e usado na primeira inicialização

O que é @AppStorage no SwiftUI?

@AppStorage é um property wrapper apresentado pela Apple no iOS 14 que vincula uma propriedade da View a uma chave no UserDefaults. Ao ler a propriedade, o SwiftUI carrega o valor do UserDefaults pela chave especificada. Ao escrever, salva o novo valor e notifica a View de que precisa ser redesenhada.

Antes do @AppStorage, os desenvolvedores tinham que ler UserDefaults manualmente no onAppear, assinar o UserDefaults.didChangeNotification e atualizar @State nas mudanças. O @AppStorage automatiza todo o ciclo: uma declaração de uma linha substitui 15–20 linhas de código repetitivo. Além disso, @AppStorage fornece sincronização bidirecional — se o valor do UserDefaults mudar de outro processo (por exemplo, App Extension ou Widget), a View ainda receberá a atualização.

Arquitetonicamente, @AppStorage é implementado como DynamicProperty, o que permite ao SwiftUI rastrear dependências e redesenhar a View quando o valor observado muda. Isso o torna ideal para armazenar configurações do usuário: idioma da interface, ativação/desativação de recursos, última aba selecionada, nome do usuário.

@AppStorage vs UserDefaults: Comparação

Embora @AppStorage use UserDefaults internamente, as abordagens para trabalhar com armazenamento são fundamentalmente diferentes. UserDefaults é uma API de baixo nível que requer gerenciamento manual de leitura, escrita e notificações de mudança. @AppStorage é uma abstração do SwiftUI que fornece comportamento reativo pronto para uso.

UserDefaults é adequado para operações únicas: carregar configurações na inicialização do aplicativo, escrever análises, armazenar tokens em cache. @AppStorage é para configurações que devem atualizar a UI reativamente: alternadores de tema, seleção de idioma, salvar o estado da interface. Usar UserDefaults diretamente dentro de uma View é um antipadrão, pois a View não sabe sobre mudanças sem assinatura adicional.

Parâmetro@AppStorageUserDefaults
ReatividadeAutomáticaRequer assinatura de notificações
Boilerplate1 linha por propriedade15–20 linhas por propriedade
TiposString, Int, Double, Bool, Data, URLTodos os tipos + objetos arquivados
Tipos personalizadosVia RawRepresentableVia NSKeyedArchiver
App ExtensionSincronização automáticaAssinatura manual

Para configurações simples com UI reativa @AppStorage é a escolha preferida. Para dados complexos (arrays, dicionários, objetos personalizados) use uma combinação de UserDefaults com @State e assinatura manual de mudanças, ou mude para SwiftData / Core Data para armazenamento estruturado.

Tipos de Dados Suportados

@AppStorage suporta tipos padrão que UserDefaults pode serializar diretamente: String, Int, Double, Bool, Data, URL. Para cada tipo existe uma versão opcional (String?, Int?, Double?, Bool?, Data?, URL?), permitindo distinguir entre "não definido" e "valor vazio".

Para armazenar tipos personalizados que estão em conformidade com o protocolo RawRepresentable, @AppStorage também funciona automaticamente. Se um enum tem rawValue do tipo String ou Int, ele pode ser usado diretamente: @AppStorage("theme") var theme: AppTheme = .system. SwiftUI serializa/desserializa automaticamente o valor via rawValue.

swift
enum AppTheme: String {
    case system, light, dark
}

struct SettingsView: View {
    @AppStorage("username") var username: String = "Guest"
    @AppStorage("launchCount") var launchCount: Int = 0
    @AppStorage("isDarkMode") var isDarkMode: Bool = false
    @AppStorage("appTheme") var theme: AppTheme = .system
    @AppStorage("lastOpened") var lastOpened: Date? = nil

    var body: some View {
        Form {
            TextField("Username", text: $username)
            Toggle("Dark mode", isOn: $isDarkMode)
            Text("Iniciada \(launchCount) vezes")
        }
    }
}

O exemplo usa diferentes tipos de @AppStorage: String com valor padrão "Guest", Int para um contador de inicializações, Bool para tema escuro, enum AppTheme com rawValue do tipo String e um Date? opcional para a última hora de abertura. Cada propriedade está vinculada a uma chave UserDefaults especificada como primeiro argumento. O valor padrão é usado se a chave não estiver presente no armazenamento na primeira inicialização.

Observação de Mudanças no Armazenamento

Uma das principais vantagens do @AppStorage é a observação automática de mudanças do UserDefaults de qualquer fonte. Se uma App Extension ou Widget muda um valor, o @AppStorage no aplicativo pai recebe a notificação e redesenha a View. Isso é alcançado através do mecanismo KVO (Key-Value Observing) que o @AppStorage configura automaticamente no UserDefaults.didChangeNotification.

Na prática, isso significa que se o usuário mudar uma configuração em um Widget (por exemplo, ativar o tema escuro), o aplicativo captura imediatamente a mudança. A mesma sincronização funciona entre o aplicativo principal e Share Extension, Watch App ou Today Widget. O desenvolvedor não precisa escrever código para troca de dados entre processos — @AppStorage faz isso automaticamente.

swift
struct ThemeSettingView: View {
    @AppStorage("isDarkMode") var isDarkMode: Bool = false

    var body: some View {
        VStack {
            Toggle("Dark Mode", isOn: $isDarkMode)
                .onChange(of: isDarkMode) { oldValue, newValue in
                    print("Modo escuro alterado para \(newValue)")
                }
        }
    }
}

Toggle está vinculado a $isDarkMode via @AppStorage. Ao alternar, o valor é automaticamente salvo em UserDefaults sob a chave "isDarkMode". O modificador .onChange permite executar um efeito colateral na mudança — por exemplo, enviar análises ou atualizar a UI de outras telas. Se um Widget mudar a mesma chave, @AppStorage também acionará onChange, garantindo consistência de estado.

Exemplos de Código @AppStorage

Vamos ver uma tela completa de configurações do aplicativo que usa @AppStorage para armazenar todas as configurações. O formulário contém seções com diferentes tipos de configurações: campos de texto, alternadores, contadores — todos os valores são automaticamente salvos em UserDefaults.

swift
struct AppSettingsView: View {
    @AppStorage("displayName") var displayName = ""
    @AppStorage("notificationsEnabled") var notificationsEnabled = true
    @AppStorage("maxResults") var maxResults = 25
    @AppStorage("selectedTab") var selectedTab = "home"

    var body: some View {
        NavigationStack {
            Form {
                Section(header: Text("Perfil")) {
                    TextField("Display name", text: $displayName)
                }

                Section(header: Text("Preferências")) {
                    Toggle("Enable notifications",
                           isOn: $notificationsEnabled)
                    Stepper("Max results: \(maxResults)",
                           value: $maxResults,
                           in: 10...100,
                           step: 5)
                }

                Section {
                    Button("Redefinir configurações") {
                        UserDefaults.standard.removePersistentDomain(
                            forName: Bundle.main.bundleIdentifier!)
                    }
                    .tint(.red)
                }
            }
            .navigationTitle("Settings")
        }
    }
}

O formulário contém quatro propriedades @AppStorage de diferentes tipos: String para o nome, Bool para notificações, Int para a quantidade de resultados e String para a aba selecionada. Todos os controles estão vinculados às propriedades via Binding ($displayName, $notificationsEnabled, etc.). O botão "Reset settings" limpa todos os UserDefaults removendo o domínio do aplicativo — depois disso @AppStorage retorna automaticamente aos valores padrão.

Sincronização do @AppStorage com App Group

swift
struct SharedSettingsView: View {
    let sharedDefaults = UserDefaults(suiteName: "group.com.example.app")

    @AppStorage("widgetTheme", store: UserDefaults(suiteName: "group.com.example.app")!)
    var widgetTheme: String = "sistema"

    @AppStorage("widgetColor", store: UserDefaults(suiteName: "group.com.example.app")!)
    var widgetColor: String = "azul"

    var body: some View {
        Form {
            Picker("Widget theme", selection: $widgetTheme) {
                Text("Sistema").tag("system")
                Text("Claro").tag("claro")
                Text("Escuro").tag("escuro")
            }
            Picker("Accent color", selection: $widgetColor) {
                Text("Azul").tag("blue")
                Text("Verde").tag("verde")
                Text("Vermelho").tag("vermelho")
            }
        }
    }
}

Para App Group (armazenamento compartilhado entre o aplicativo e extensões) @AppStorage aceita o parâmetro store: UserDefaults(suiteName:). Os valores são salvos no contêiner compartilhado disponível para o aplicativo principal, Widget, Watch App e outras extensões do mesmo grupo. Um Widget pode ler essas configurações, e quando elas mudam no aplicativo, o Widget é atualizado automaticamente através do mecanismo de observação do UserDefaults.

Perguntas Frequentes

Qual é a diferença entre @AppStorage e @State?

@State armazena o valor apenas na memória e é redefinido quando o aplicativo reinicia. @AppStorage salva o valor em UserDefaults e o restaura na próxima inicialização. Use @State para dados temporários de tela, @AppStorage para configurações que devem sobreviver a uma reinicialização.

Posso usar @AppStorage com Enum?

Sim, se o Enum implementar o protocolo RawRepresentable com rawValue do tipo String ou Int. Exemplo: @AppStorage("theme") var theme: AppTheme = .system. SwiftUI serializa automaticamente o enum via rawValue e o restaura ao carregar.

Como limpar todos os valores de @AppStorage?

Chame UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!) para o armazenamento padrão ou removeObject(forKey:) para uma chave específica. Após limpar, todas as propriedades @AppStorage retornarão aos valores padrão especificados na declaração.

@AppStorage funciona com App Extensions?

Sim, para sincronização entre o aplicativo e extensões use App Group: @AppStorage("key", store: UserDefaults(suiteName: "group.com.example.app")!). Widget, Share Extension e Watch App podem ler e escrever no mesmo UserDefaults, e as mudanças são rastreadas automaticamente.

Quanto dados podem ser armazenados em @AppStorage?

@AppStorage usa UserDefaults, que é projetado para pequenas quantidades de dados: configurações, tokens, contadores. O limite recomendado é de até 100 KB por aplicativo. Para dados estruturados ou grandes (arrays de objetos, arquivos de mídia) use SwiftData, Core Data ou o sistema de arquivos.

Resumo

  • @AppStorage — property wrapper para armazenamento reativo de configurações em UserDefaults
  • Auto-salvamento e auto-atualização da UI quando o valor muda de qualquer fonte
  • Suporta String, Int, Double, Bool, Data, URL e enums RawRepresentable
  • Valor padrão é definido na declaração e restaurado na primeira inicialização
  • App Group permite sincronizar @AppStorage entre o aplicativo e extensões
  • UserDefaults é adequado apenas para pequenas quantidades de dados — até 100 KB
  • Use @AppStorage para configurações do usuário, @State para estados temporários de tela

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