@ObservedObject: qué es, observación de objetos y actualización de Views

Autor: IT Sectr Publicado: 2026-06-26 Tiempo de lectura: 9 min

@ObservedObject es un property wrapper en SwiftUI que permite a una View observar cambios en un ObservableObject creado en otro lugar de la jerarquía. A diferencia de @StateObject, @ObservedObject no crea el objeto — solo se suscribe a su publisher objectWillChange y redibuja la View cuando se actualizan las propiedades publicadas. Esto hace que @ObservedObject sea la opción correcta para Views hijas que reciben datos de un padre a través de un inicializador. Según un artículo de Paul Hudson — Hacking with Swift (2025), una arquitectura típica de aplicación SwiftUI se construye así: la View raíz usa @StateObject para crear un view model, y todas las Views hijas lo reciben a través de @ObservedObject, garantizando una única fuente de verdad sin duplicación de datos.

Puntos clave

  • @ObservedObject — un property wrapper para observar un ObservableObject creado en una View padre.
  • No posee el objeto — a diferencia de @StateObject, @ObservedObject no gestiona el ciclo de vida del objeto.
  • Se suscribe a cambios — cuando las propiedades @Published cambian, la View se redibuja automáticamente.
  • Se pasa por inicializador — el objeto se pasa a la View hija a través de un parámetro del inicializador.
  • iOS 13+ — @ObservedObject está disponible desde la primera versión de SwiftUI, a diferencia de @StateObject (iOS 14+).

Qué es @ObservedObject en SwiftUI

@ObservedObject es un property wrapper que suscribe una View a los cambios de ObservableObject. Cuando un objeto marcado con @ObservedObject cambia alguna de sus propiedades declaradas con @Published, SwiftUI redibuja automáticamente la View. @ObservedObject no crea el objeto — solo establece una conexión entre una instancia existente de ObservableObject y la View que debe reaccionar a sus cambios.

La diferencia clave entre @ObservedObject y @StateObject es la propiedad. @ObservedObject asume que el objeto se crea y almacena en algún lugar más arriba en la jerarquía de Views. La View hija recibe una referencia a este objeto a través del inicializador y simplemente lo observa. Si la View hija se recrea, recibe la misma referencia del padre — los datos no se pierden.

Según Apple Developer Documentation — SwiftUI (2025), @ObservedObject está disponible desde iOS 13, lo que lo convierte en la única opción para observar ObservableObject en proyectos que admiten versiones antiguas de iOS. En iOS 14+ se prefiere @StateObject para crear objetos, pero @ObservedObject sigue siendo relevante para pasar objetos existentes.

Cómo funciona @ObservedObject

El mecanismo de @ObservedObject se basa en el protocolo ObservableObject del framework Combine. Cada clase que conforma ObservableObject obtiene automáticamente un publisher objectWillChange que envía una señal antes de que cualquier propiedad @Published cambie. SwiftUI se suscribe a este publisher a través de @ObservedObject y al recibir la señal marca la View como necesitada de redibujado.

swift
class TaskViewModel: ObservableObject {
    @Published var tasks: [Task] = []
    @Published var isLoading = false
    
    func loadTasks() async {
        isLoading = true
        // fetch data
        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() }
    }
}

Cuando la View padre pasa viewModel a TaskListView a través del inicializador, SwiftUI crea una conexión entre el objeto y la View. Cuando el array tasks o el flag isLoading cambian, SwiftUI redibuja TaskListView. El objeto en sí permanece sin cambios — se almacena en la View padre a través de @StateObject.

@ObservedObject vs @StateObject: cuándo usar cada uno

La diferencia entre @ObservedObject y @StateObject es la diferencia entre un observador y un propietario. @StateObject crea el objeto y gestiona su ciclo de vida. @ObservedObject solo observa un objeto que fue creado y almacenado en otro lugar. La elección entre ellos está determinada por la responsabilidad de la View sobre los datos.

EscenarioRecomendaciónMotivo
La View crea datos@StateObjectLa View posee el objeto y es responsable de su ciclo de vida
La View recibe datos@ObservedObjectLa View solo observa, el objeto vive en el padre
Soporte iOS 13@ObservedObject@StateObject no está disponible, usa @ObservedObject con gestión manual
Componente reutilizable@ObservedObjectEl componente no debe crear datos — los recibe externamente

La regla principal: si la View crea el objeto — @StateObject. Si la View recibe el objeto — @ObservedObject. Violar esta regla usando @ObservedObject para crear un objeto provoca pérdida de datos cuando la View se reconstruye. Violarla usando @StateObject para recibir un objeto crea una instancia duplicada independiente del padre.

Ejemplos de uso de @ObservedObject

Un escenario típico de uso de @ObservedObject es una lista de tareas donde la View raíz crea un view model y cada celda de la lista lo recibe a través de @ObservedObject. Cada celda puede llamar a métodos del view model, y los cambios se reflejan automáticamente en toda la lista ya que todas las celdas observan el mismo objeto.

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

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

En este ejemplo, TaskListContainer crea viewModel a través de @StateObject, y cada TaskRow lo recibe a través de @ObservedObject. Cuando el usuario presiona “Done” en cualquier fila, viewModel.completeTask cambia una propiedad publicada, y todas las Views que observan este objeto se actualizan automáticamente.

Errores comunes con @ObservedObject

El error más común es usar @ObservedObject para crear un objeto dentro de una View. Cuando la View se reconstruye (por ejemplo, al cambiar el estado), SwiftUI crea una nueva instancia de ObservableObject, lo que provoca la pérdida de todos los datos acumulados. Este error es especialmente doloroso en NavigationStack, donde un usuario podría rellenar un formulario y perder los datos al navegar hacia atrás.

Error: @ObservedObject en lugar de @StateObject

swift
// ❌ Pérdida de datos: @ObservedObject no retiene el objeto
struct FormView: View {
    @ObservedObject var formVM = FormViewModel()
    // ¡Nuevo formVM creado en cada reconstrucción de View!
}

// ✅ Correcto: @StateObject retiene el objeto
struct FormView: View {
    @StateObject var formVM = FormViewModel()
    // Objeto creado una vez por ciclo de vida de la View
}

Error: pasar @StateObject donde se necesita @ObservedObject

Si una View hija declara el mismo ObservableObject a través de @StateObject, crea una copia independiente. Los cambios en el objeto padre no serán visibles en la hija, y viceversa. Usa siempre @ObservedObject para Views hijas que reciben el objeto externamente.

Alternativas a @ObservedObject en SwiftUI

En SwiftUI moderno existen varias alternativas a @ObservedObject, cada una con sus ventajas. La elección depende de la arquitectura de la aplicación, la versión de iOS y el caso de uso específico.

  • @EnvironmentObject — permite obtener un objeto del entorno SwiftUI sin pasarlo explícitamente a través del inicializador. Conveniente para objetos necesarios en muchas pantallas, pero requiere inyección explícita mediante .environmentObject().
  • @State + @Binding — para tipos de valor simples no se necesita ObservableObject. Usa @State para almacenar y @Binding para pasar a Views hijas.
  • @AppStorage — para valores de UserDefaults que deben sincronizarse automáticamente con la View.
  • @SceneStorage — para preservar el estado temporal entre reinicios de escena (por ejemplo, posición de desplazamiento en una lista).

La elección entre @ObservedObject y @EnvironmentObject es una cuestión de estilo y arquitectura. @ObservedObject muestra explícitamente las dependencias de la View a través del inicializador, haciendo el código más predecible. @EnvironmentObject es conveniente para jerarquías profundas pero oculta las dependencias, lo que puede dificultar la depuración.

Preguntas frecuentes

¿Se puede usar @ObservedObject sin @StateObject en el padre?

Sí, si el objeto se crea y almacena fuera de SwiftUI — por ejemplo, en un AppDelegate o singleton. En este caso, @ObservedObject simplemente se suscribe a los cambios de un objeto existente. Sin embargo, para objetos creados dentro de la jerarquía SwiftUI, siempre se necesita @StateObject en algún nivel superior.

¿Por qué a veces @ObservedObject no actualiza la View?

La razón más probable es que la propiedad se cambia no a través de @Published o que el objeto en sí no se modifica sino que su estructura interna muta sin llamar a objectWillChange. Para colecciones, usa la asignación de una nueva copia: array.append() no es suficiente — necesitas reasignar el array mediante array = array + [element].

¿Afecta @ObservedObject al rendimiento?

@ObservedObject por sí mismo no genera una sobrecarga significativa. Los problemas surgen con cambios frecuentes de propiedades @Published — cada cambio desencadena un redibujado de todas las Views observadoras. Para optimizar, usa EquatableView, reduce el número de propiedades publicadas y evita actualizaciones innecesarias.

¿En qué se diferencia @ObservedObject de @Binding?

@ObservedObject observa una clase ObservableObject completa y redibuja la View ante cualquier cambio en sus propiedades publicadas. @Binding crea una conexión bidireccional con un valor específico (String, Int, Bool) y permite leerlo y escribirlo. @Binding es más ligero y no requiere ObservableObject.

¿Se puede combinar @ObservedObject con @Published en la misma clase?

Sí, este es el patrón estándar. @Published dentro de ObservableObject se integra automáticamente con @ObservedObject. Cada propiedad @Published añade un observador al publisher objectWillChange. Cuando cualquiera de ellas cambia, todas las Views con @ObservedObject para este objeto se redibujan.

Resumen

  • @ObservedObject — un property wrapper para observar un ObservableObject creado en otro lugar de la jerarquía.
  • No posee el objeto — a diferencia de @StateObject, @ObservedObject no gestiona el ciclo de vida ni crea el objeto.
  • Suscripción a través de Combine — SwiftUI se suscribe automáticamente al publisher objectWillChange del ObservableObject.
  • iOS 13+ — @ObservedObject está disponible desde la primera versión de SwiftUI, importante para proyectos con soporte heredado.
  • Se pasa por inicializador — el objeto se pasa explícitamente a la View hija, haciendo las dependencias transparentes.
  • Error de propiedad — usar @ObservedObject para crear un objeto provoca pérdida de datos al reconstruir la View.
  • Alternativas — @EnvironmentObject para inyección por entorno, @State/@Binding para tipos de valor.

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también