@ObservedObject: o que é, observação de objetos e atualização de Views

Autor: IT Sectr Publicado: 2026-06-26 Tempo de leitura: 9 min

@ObservedObject é um property wrapper em SwiftUI que permite a uma View observar alterações em um ObservableObject criado em outro lugar da hierarquia. Diferente de @StateObject, @ObservedObject não cria o objeto — ele apenas se inscreve no publisher objectWillChange e redesenha a View quando propriedades publicadas são atualizadas. Isso torna @ObservedObject a escolha certa para Views filhas que recebem dados de um pai através de um inicializador. De acordo com um artigo de Paul Hudson — Hacking with Swift (2025), uma arquitetura típica de aplicação SwiftUI é construída assim: a View raiz usa @StateObject para criar um view model, e todas as Views filhas o recebem através de @ObservedObject, garantindo uma única fonte de verdade sem duplicação de dados.

Pontos principais

  • @ObservedObject — um property wrapper para observar um ObservableObject criado em uma View pai.
  • Não possui o objeto — diferente de @StateObject, @ObservedObject não gerencia o ciclo de vida do objeto.
  • Inscrição em mudanças — quando propriedades @Published mudam, a View é redesenhada automaticamente.
  • Passado via inicializador — o objeto é passado para a View filha através de um parâmetro do inicializador.
  • iOS 13+ — @ObservedObject está disponível desde a primeira versão do SwiftUI, diferente de @StateObject (iOS 14+).

O que é @ObservedObject em SwiftUI

@ObservedObject é um property wrapper que inscreve uma View em mudanças ObservableObject. Quando um objeto marcado com @ObservedObject altera qualquer uma de suas propriedades declaradas com @Published, o SwiftUI redesenha automaticamente a View. @ObservedObject não cria o objeto — ele apenas estabelece uma conexão entre uma instância ObservableObject existente e a View que deve reagir às suas mudanças.

A diferença chave entre @ObservedObject e @StateObject é a propriedade. @ObservedObject assume que o objeto foi criado e armazenado em algum lugar mais alto na hierarquia de Views. A View filha recebe uma referência a este objeto através do inicializador e simplesmente o observa. Se a View filha for recriada, ela recebe a mesma referência do pai — os dados não se perdem.

De acordo com a Apple Developer Documentation — SwiftUI (2025), @ObservedObject está disponível desde o iOS 13, tornando-o a única opção para observar ObservableObject em projetos que suportam versões antigas do iOS. No iOS 14+, @StateObject é preferível para criar objetos, mas @ObservedObject continua relevante para passar objetos existentes.

Como funciona @ObservedObject

O mecanismo do @ObservedObject é baseado no protocolo ObservableObject do framework Combine. Cada classe em conformidade com ObservableObject obtém automaticamente um publisher objectWillChange que envia um sinal antes de qualquer alteração em propriedades @Published. O SwiftUI se inscreve neste publisher através de @ObservedObject e, ao receber o sinal, marca a View como necessitando redesenho.

swift
class TaskViewModel: ObservableObject {
    @Published var tasks: [Task] = []
    @Published var isLoading = false
    
    func loadTasks() async {
        isLoading = true
        // buscar dados
        isLoading = false
    }
}

struct TaskListView: View {
    @ObservedObject var viewModel: TaskViewModel
    
    var body: some View {
        List(viewModel.tasks) { task in
            Text(task.title)
        }
        .task { await viewModel.loadTasks() }
    }
}

Quando a View pai passa viewModel para TaskListView através do inicializador, o SwiftUI cria uma conexão entre o objeto e a View. Quando o array tasks ou a flag isLoading mudam, o SwiftUI redesenha TaskListView. O objeto em si permanece inalterado — ele é armazenado na View pai através de @StateObject.

@ObservedObject vs @StateObject: quando usar cada um

A diferença entre @ObservedObject e @StateObject é a diferença entre um observador e um proprietário. @StateObject cria o objeto e gerencia seu ciclo de vida. @ObservedObject apenas observa um objeto que foi criado e armazenado em outro lugar. A escolha entre eles é determinada pela responsabilidade da View sobre os dados.

CenárioRecomendaçãoMotivo
View cria dados@StateObjectView possui o objeto e é responsável pelo seu ciclo de vida
View recebe dados@ObservedObjectView apenas observa, o objeto vive no pai
Suporte iOS 13@ObservedObject@StateObject indisponível, use @ObservedObject com gerenciamento manual
Componente reutilizável@ObservedObjectComponente não deve criar dados — ele os recebe externamente

A regra principal: se a View cria o objeto — @StateObject. Se a View recebe o objeto — @ObservedObject. Violar esta regra usando @ObservedObject para criar um objeto leva à perda de dados quando a View é reconstruída. Violá-la usando @StateObject para receber um objeto cria uma instância duplicada independente do pai.

Exemplos de uso do @ObservedObject

Um cenário típico de uso do @ObservedObject é uma lista de tarefas onde a View raiz cria um view model e cada célula da lista o recebe através de @ObservedObject. Cada célula pode chamar métodos do view model, e as mudanças são refletidas automaticamente em toda a lista, já que todas as células observam o mesmo objeto.

swift
struct TaskRow: View {
    @ObservedObject var viewModel: TaskViewModel
    let task: Task
    
    var body: some View {
        HStack {
            Text(task.title)
            Spacer()
            Button("Concluído") {
                viewModel.completeTask(task)
            }
        }
    }
}

struct TaskListContainer: View {
    @StateObject var viewModel = TaskViewModel()
    
    var body: some View {
        List(viewModel.tasks) { task in
            TaskRow(viewModel: viewModel, task: task)
        }
    }
}

Neste exemplo, TaskListContainer cria viewModel através de @StateObject, e cada TaskRow o recebe através de @ObservedObject. Quando o usuário pressiona “Done” em qualquer linha, viewModel.completeTask altera uma propriedade publicada, e todas as Views que observam este objeto são atualizadas automaticamente.

Erros comuns com @ObservedObject

O erro mais comum é usar @ObservedObject para criar um objeto dentro de uma View. Quando a View é reconstruída (por exemplo, quando o estado muda), o SwiftUI cria uma nova instância ObservableObject, levando à perda de todos os dados acumulados. Este erro é especialmente doloroso no NavigationStack, onde um usuário pode preencher um formulário e perder os dados ao navegar de volta.

Erro: @ObservedObject em vez de @StateObject

swift
// ❌ Perda de dados: @ObservedObject não retém o objeto
struct FormView: View {
    @ObservedObject var formVM = FormViewModel()
    // Novo formVM criado em cada reconstrução de View!
}

// ✅ Correto: @StateObject retém o objeto
struct FormView: View {
    @StateObject var formVM = FormViewModel()
    // Objeto criado uma vez por vida útil da View
}

Erro: passar @StateObject onde @ObservedObject é necessário

Se uma View filha declara o mesmo ObservableObject através de @StateObject, ela cria uma cópia independente. Alterações no objeto pai não serão visíveis na filha, e vice-versa. Sempre use @ObservedObject para Views filhas que recebem o objeto externamente.

Alternativas ao @ObservedObject em SwiftUI

No SwiftUI moderno existem várias alternativas ao @ObservedObject, cada uma com suas vantagens. A escolha depende da arquitetura da aplicação, da versão do iOS e do caso de uso específico.

  • @EnvironmentObject — permite obter um objeto do ambiente SwiftUI sem passá-lo explicitamente pelo inicializador. Conveniente para objetos necessários em muitas telas, mas requer injeção explícita através de .environmentObject().
  • @State + @Binding — para tipos de valor simples, ObservableObject não é necessário. Use @State para armazenar e @Binding para passar para Views filhas.
  • @AppStorage — para valores UserDefaults que devem sincronizar automaticamente com a View.
  • @SceneStorage — para preservar estado temporário entre reinícios de cena (por exemplo, posição de rolagem em uma lista).

A escolha entre @ObservedObject e @EnvironmentObject é uma questão de estilo e arquitetura. @ObservedObject mostra explicitamente as dependências da View através do inicializador, tornando o código mais previsível. @EnvironmentObject é conveniente para hierarquias profundas, mas esconde dependências, o que pode dificultar a depuração.

Perguntas frequentes

Pode-se usar @ObservedObject sem @StateObject no pai?

Sim, se o objeto for criado e armazenado fora do SwiftUI — por exemplo, em um AppDelegate ou singleton. Neste caso, @ObservedObject simplesmente se inscreve nas mudanças de um objeto existente. No entanto, para objetos criados dentro da hierarquia SwiftUI, @StateObject é sempre necessário em algum nível superior.

Por que @ObservedObject às vezes não atualiza a View?

A razão mais provável é que a propriedade é alterada não através de @Published ou o objeto em si não é alterado, mas sua estrutura interna sofre mutação sem chamar objectWillChange. Para coleções, use atribuição de uma nova cópia: array.append() não é suficiente — você precisa reatribuir o próprio array através de array = array + [element].

@ObservedObject afeta o desempenho?

@ObservedObject por si só não cria sobrecarga significativa. Os problemas surgem com alterações frequentes de propriedades @Published — cada mudança dispara um redesenho de todas as Views observadoras. Para otimizar, use EquatableView, reduza o número de propriedades publicadas e evite atualizações desnecessárias.

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

@ObservedObject observa uma classe ObservableObject inteira e redesenha a View em qualquer alteração em suas propriedades publicadas. @Binding cria uma conexão bidirecional com um valor específico (String, Int, Bool) e permite lê-lo e escrevê-lo. @Binding é mais leve e não requer ObservableObject.

Pode-se combinar @ObservedObject com @Published na mesma classe?

Sim, este é o padrão normal. @Published dentro de ObservableObject integra-se automaticamente com @ObservedObject. Cada propriedade @Published adiciona um observador ao publisher objectWillChange. Quando qualquer uma delas muda, todas as Views com @ObservedObject para este objeto são redesenhadas.

Resumo

  • @ObservedObject — um property wrapper para observar um ObservableObject criado em outro lugar da hierarquia.
  • Não possui o objeto — diferente de @StateObject, @ObservedObject não gerencia o ciclo de vida nem cria o objeto.
  • Inscrição através do Combine — SwiftUI se inscreve automaticamente no publisher objectWillChange do ObservableObject.
  • iOS 13+ — @ObservedObject está disponível desde a primeira versão do SwiftUI, importante para projetos com suporte herdado.
  • Passado via inicializador — o objeto é passado explicitamente para a View filha, tornando as dependências transparentes.
  • Erro de propriedade — usar @ObservedObject para criar um objeto leva à perda de dados ao reconstruir a View.
  • Alternativas — @EnvironmentObject para injeção por ambiente, @State/@Binding para tipos de valor.

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