@StateObject: qué es, creación y gestión de ObservableObject

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

@StateObject es un property wrapper en SwiftUI que crea y posee una instancia de ObservableObject durante todo el ciclo de vida de una View. Cuando una View aparece por primera vez en pantalla, @StateObject inicializa el objeto y lo almacena hasta que la View se elimina de la memoria. Esto garantiza que los datos no se restablezcan al reconstruir la interfaz, por ejemplo, al cambiar el tema o actualizar la View padre. Según la Documentación para Desarrolladores de Apple (2025), @StateObject debe usarse como la fuente principal de verdad (source of truth) para ObservableObject en la jerarquía de SwiftUI, mientras que las Views hijas reciben el objeto ya creado a través de @ObservedObject o @EnvironmentObject.

Puntos Clave

  • @StateObject es un property wrapper para crear y poseer un ObservableObject dentro de una View.
  • Creación única — el objeto se inicializa una vez durante la vida de la View y no se recrea en las reconstrucciones.
  • Fuente de verdad — @StateObject es la fuente de verdad en la jerarquía, a diferencia de @ObservedObject.
  • Ciclo de vida — el objeto vive mientras la View existe en memoria y se destruye junto con ella.
  • Inicialización — @StateObject requiere un valor inicial en la creación, normalmente a través de init con parámetros.

Qué es @StateObject en SwiftUI

@StateObject es un property wrapper introducido en iOS 14 que permite a una View crear y poseer una instancia de una clase que cumpla con el protocolo ObservableObject. A diferencia de @State, que trabaja con tipos de valor (structs), @StateObject está diseñado para tipos de referencia — clases que pueden notificar a SwiftUI sobre cambios en sus propiedades.

Cuando una View usa @StateObject var viewModel: MyViewModel, SwiftUI crea automáticamente una instancia de MyViewModel cuando la View aparece por primera vez y la almacena en un almacenamiento especial del framework. En cada actualización de la View (por ejemplo, cuando cambia el estado padre), SwiftUI no recrea el objeto — usa la instancia existente hasta que la View se elimina de la jerarquía.

Según Apple WWDC Session 10137 (2024), @StateObject resuelve el problema de pérdida de datos que existía en iOS 13 cuando las Views se reconstruían, obligando a los desarrolladores a crear ObservableObject en la View padre y pasarlo a través del inicializador. Esto provocaba duplicación de código y el riesgo de recrear accidentalmente el objeto.

swift
import SwiftUI

class CounterViewModel: ObservableObject {
    @Published var count: Int = 0
    
    func increment() {
        count += 1
    }
}

struct CounterView: View {
    @StateObject var viewModel = CounterViewModel()
    
    var body: some View {
        VStack {
            Text("Count: \(viewModel.count)")
            Button("Increment", action: viewModel.increment)
        }
    }
}

Cómo funciona @StateObject

El mecanismo de @StateObject se basa en la integración de SwiftUI con el framework Combine. Cuando un ObservableObject marca sus propiedades con el atributo @Published, SwiftUI se suscribe automáticamente a los cambios a través del publisher integrado en el protocolo ObservableObject. Cuando una propiedad publicada cambia, el objeto envía una señal a través del publisher objectWillChange, lo que desencadena un redibujado de todas las Views que observan este objeto.

SwiftUI almacena la instancia de ObservableObject en un almacenamiento especial vinculado a una instancia específica de View. Este almacenamiento se crea una vez durante el primer renderizado y existe hasta que la View se destruye. Por eso @StateObject garantiza la estabilidad de la referencia — SwiftUI gestiona la memoria automáticamente, sin depender del inicializador de la View.

Según objc.io — Thinking in SwiftUI (2025), la implementación interna de @StateObject utiliza un mecanismo similar a @State pero para tipos de referencia: SwiftUI crea una envoltura (boxing) alrededor del objeto y gestiona su ciclo de vida a través de su propio asignador, optimizado para reconstrucciones frecuentes de la jerarquía de Views.

Ciclo de vida de @StateObject

  • Creación — cuando la View aparece por primera vez en pantalla, SwiftUI llama al inicializador del objeto y almacena la referencia.
  • Reconstrucción — cuando la View padre se actualiza, el objeto no se recrea; se usa la instancia existente.
  • Destrucción — cuando la View sale de la pantalla y se elimina de la jerarquía, SwiftUI llama al deinit del objeto.

@StateObject vs @ObservedObject: diferencias clave

La principal diferencia entre @StateObject y @ObservedObject radica en quién posee el objeto. @StateObject crea y almacena el objeto — es el propietario. @ObservedObject solo observa el objeto que fue creado en otro lugar y pasado a través del inicializador o una propiedad.

Característica@StateObject@ObservedObject
PropiedadCrea y posee el objetoSolo observa
InicializaciónDentro de la View mediante init/defaultExterna, se pasa mediante parámetro
Ciclo de vidaVinculado al ciclo de vida de la ViewNo controlado por la View
RecreaciónNo se recrea al actualizarPuede ser reemplazado externamente
Versión de iOSiOS 14+iOS 13+

La regla es simple: si la View crea el ObservableObject — usa @StateObject. Si la View solo recibe un objeto ya creado del padre — usa @ObservedObject. Violar esta regla lleva a la pérdida de datos (si se usa @ObservedObject para la propiedad) o a la creación excesiva de objetos (si se usa @StateObject para la observación).

Cuándo usar @StateObject

@StateObject debe usarse en las Views que son la fuente de verdad para un conjunto específico de datos. Los escenarios típicos incluyen pantallas con su propio view model, pantallas raíz de pilas de navegación y presentaciones modales que gestionan su propio estado.

  • Pantalla con view model — cada pantalla que gestiona sus propios datos y lógica debe crear su view model a través de @StateObject.
  • View raíz — en una jerarquía de NavigationStack o TabView, el elemento raíz crea los datos y los elementos hijos los reciben a través de @ObservedObject.
  • Ventanas modales — .sheet y .fullScreenCover a menudo requieren su propio @StateObject para gestionar un formulario o proceso.
  • Lista editable — cada fila de lista que contiene un formulario de edición debe tener su propio @StateObject.
swift
struct ProfileView: View {
    @StateObject var viewModel = ProfileViewModel()
    
    var body: some View {
        NavigationStack {
            Form {
                TextField("Name", text: $viewModel.name)
                TextField("Email", text: $viewModel.email)
                Button("Save") {
                    viewModel.saveProfile()
                }
            }
            .navigationTitle("Profile")
        }
    }
}

Inicializar @StateObject con parámetros

Inicializar @StateObject con parámetros requiere una sintaxis especial, ya que SwiftUI gestiona la creación del objeto por sí mismo. No se pueden pasar simplemente parámetros al inicializador — hay que usar un closure escapado o un método de fábrica separado.

Según Swift by Sundell (2024), el enfoque más limpio es usar un método de fábrica o closure que SwiftUI llamará cuando el objeto se cree por primera vez. Un enfoque alternativo es inicializar el ObservableObject en la View padre y pasarlo a través de @StateObject usando el inicializador estándar.

swift
class UserViewModel: ObservableObject {
    @Published var user: User
    
    init(user: User) {
        self.user = user
    }
}

struct UserDetailView: View {
    @StateObject var viewModel: UserViewModel
    
    init(user: User) {
        _viewModel = StateObject(wrappedValue: UserViewModel(user: user))
    }
    
    var body: some View {
        Text(viewModel.user.name)
    }
}

Es importante recordar que el inicializador de View con @StateObject debe usar un guion bajo antes del nombre de la propiedad (_viewModel) para acceder al property wrapper en sí, no a su valor. Este es un patrón estándar de Swift para trabajar con property wrappers en inicializadores.

Errores comunes con @StateObject

El error más común es usar @ObservedObject en lugar de @StateObject para una View que debería poseer el objeto. En este caso, cada vez que se reconstruye el padre, el objeto se recrea, lo que provoca la pérdida de todos los datos acumulados. Este error es especialmente peligroso en jerarquías complejas con NavigationStack o TabView.

  • Pérdida de datos durante la navegación — si una pantalla hija usa @ObservedObject para su propio view model, los datos se restablecerán al navegar hacia atrás y volver a abrir.
  • Fuga de memoria — crear @StateObject en una View padre que nunca se elimina puede llevar a la acumulación de objetos si cada pantalla hija también crea @StateObject sin control.
  • Duplicación de objetos — pasar un único ObservableObject a múltiples @StateObject en diferentes Views crea varias instancias independientes que no se sincronizan entre sí.

Para evitar estos problemas, sigue una regla simple: un @StateObject por fuente de verdad. Si los datos deben compartirse entre varias pantallas — crea @StateObject una vez en la View raíz y pásalo a través de @ObservedObject o @EnvironmentObject a los elementos hijos.

swift
// ❌ Wrong: @ObservedObject for owning an object
struct BadView: View {
    @ObservedObject var vm = ViewModel() // will be recreated on each update!
}

// ✅ Correct: @StateObject for owning
struct GoodView: View {
    @StateObject var vm = ViewModel() // created once for View lifetime
}

Preguntas Frecuentes

¿Cuál es la diferencia entre @StateObject y @State?

@State trabaja con tipos de valor (structs, strings, números) y almacena el valor directamente en el almacenamiento de SwiftUI. @StateObject trabaja con tipos de referencia — clases que cumplen con ObservableObject. @State es adecuado para estados locales simples, @StateObject para objetos complejos con lógica y propiedades publicadas.

¿Puedo usar @StateObject en iOS 13?

No, @StateObject solo está disponible desde iOS 14 en adelante. Para iOS 13, usa @ObservedObject y crea el ObservableObject en la View padre a través de @State con gestión manual del ciclo de vida. Una alternativa es usar @State con un struct en lugar de una clase para datos que no requieren semántica de referencia.

¿Qué sucede si uso @StateObject en una View hija donde el objeto se pasa desde el padre?

La View hija creará su propia copia del ObservableObject, completamente independiente de la del padre. Los cambios en uno no afectarán al otro. Esto es casi siempre un error: usa @ObservedObject para recibir un objeto del padre y @StateObject solo para crear un nuevo objeto dentro de la View.

¿Cuándo se destruye un objeto creado con @StateObject?

El objeto se destruye cuando la View que lo creó se elimina completamente de la jerarquía de SwiftUI. Para una pantalla en NavigationStack, esto ocurre al hacer pop de la pila de navegación. Para una ventana modal — cuando se cierra. Para TabView — al cambiar de pestaña, si la View no está en caché.

¿Cómo pasar parámetros a @StateObject durante la inicialización?

Usa un init personalizado con acceso al property wrapper mediante guion bajo: _viewModel = StateObject(wrappedValue: MyViewModel(param: value)). Este patrón permite pasar cualquier parámetro al ObservableObject manteniendo la garantía de creación única del objeto durante la vida de la View.

Resumen

  • @StateObject — un property wrapper para crear y poseer un ObservableObject dentro de una View, disponible desde iOS 14.
  • Garantía de creación única — el objeto se inicializa una vez y no se recrea al reconstruir la View.
  • Fuente de verdad — @StateObject es la fuente de verdad, mientras que @ObservedObject es solo un observador.
  • Ciclo de vida — el objeto vive mientras la View existe en la jerarquía de SwiftUI y se destruye al salir de ella.
  • Inicialización con parámetros — requiere acceso al property wrapper mediante _viewModel y StateObject(wrappedValue:).
  • Error de propiedad — usar @ObservedObject para crear un objeto provoca pérdida de datos al reconstruir.
  • Un objeto — un @StateObject — para datos compartidos, crea @StateObject en la View raíz y pásalo a las hijas mediante @ObservedObject.

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