@State — qué es, propósito y uso en SwiftUI

Autor: IT Sectr Publicado: 2026-06-19 Tiempo de lectura: 7 min

@State es un Property Wrapper en SwiftUI para gestionar el estado local dentro de una sola vista. SwiftUI redibuja automáticamente la vista cada vez que cambia una propiedad @State, haciendo que la interfaz sea reactiva sin llamadas manuales de actualización. Según Apple Developer Documentation (2025), @State se recomienda para tipos simples y estructuras que pertenecen a una sola vista. @State es la forma más sencilla de añadir interactividad a una interfaz SwiftUI.

Puntos clave

  • @State — Property Wrapper para estado local perteneciente a una sola vista
  • Actualización automática — SwiftUI reinvoca body cuando cambia una propiedad @State
  • Tipos simples — @State funciona con String, Int, Bool, enum y structs
  • No pasar a vistas hijas — usa @Binding para cambios desde componentes hijos
  • private — las propiedades @State siempre se declaran con el modificador private

¿Qué es @State en SwiftUI?

@State es un Property Wrapper integrado en SwiftUI que permite a una vista almacenar y rastrear su propio estado. Cuando un valor @State cambia, SwiftUI redibuja automáticamente la vista reinvocando la propiedad body. Esta es la base de la programación reactiva en SwiftUI: el desarrollador declara el estado y el framework se encarga de la sincronización de la interfaz.

@State crea un área de almacenamiento en el heap gestionada por SwiftUI. Esta área es persistente — sobrevive a inicializaciones repetidas de la estructura de la vista, que ocurren en cada renderizado. SwiftUI utiliza el identificador de la vista (generado a partir de su posición en la jerarquía) para vincular la propiedad @State a una vista específica. Gracias a esto, el estado no se restablece cuando se actualiza la vista padre.

Una limitación importante: @State está diseñado solo para tipos de valor (structs, enums, primitivos). Para tipos de referencia (clases), usa @StateObject o @ObservedObject. Si asignas una clase a una propiedad @State, SwiftUI no podrá detectar cambios dentro del objeto — solo un reemplazo completo de la referencia.

¿Cómo funciona @State internamente?

SwiftUI implementa @State a través de un mecanismo interno de Storage. Cada propiedad @State obtiene una celda de memoria dedicada almacenada en un contenedor de almacenamiento especial de la vista. Cuando ocurre una escritura en wrappedValue, SwiftUI notifica a su grafo de dependencias mediante didSet sobre la necesidad de redibujar.

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

    var body: some View {
        VStack {
            Text("Hola, \(name)")
            Button(isLoggedIn ? "Cerrar sesión" : "Iniciar sesión") {
                isLoggedIn.toggle()
            }
        }
    }
}

En el ejemplo, hay dos propiedades @State: name (String) e isLoggedIn (Bool). Cuando se llama a isLoggedIn.toggle(), SwiftUI marca ContentView como necesitada de actualización y reinvoca body en el siguiente ciclo de renderizado. El punto clave: las propiedades @State siempre se declaran con el modificador private — esto indica que el estado pertenece exclusivamente a la vista actual y no debe cambiarse desde fuera directamente.

Para observar cambios, SwiftUI utiliza CurrentValueSubject de Combine. Cada propiedad @State crea un publicador oculto que notifica al sistema en cada cambio. Esto permite a SwiftUI redibujar solo el conjunto mínimo necesario de vistas, evitando actualizaciones completas de la jerarquía.

Cuándo usar @State en un proyecto

@State es óptimo para estados locales simples: campos de texto en búsqueda, indicadores booleanos para ventanas modales, interruptores de configuración, contadores, elementos seleccionados de lista. Si un valor se usa solo en una vista y sus componentes hijos (a través de @Binding), @State es la elección correcta. Para estados que deben sobrevivir al cierre de la vista (por ejemplo, datos de formulario), @State también funciona mientras la vista permanezca en la jerarquía.

  • Campos de texto — @State para almacenar texto ingresado en TextField
  • Indicadores booleanos — @State para mostrar/ocultar ventanas modales y sheets
  • Selección de elementos — @State para rastrear la pestaña o fila seleccionada
  • Contadores — @State para valores numéricos con incremento/decremento
  • Cálculos intermedios — @State para almacenar en caché resultados dentro de una vista

No uses @State para estados globales de la aplicación, almacenamiento en caché de datos de red u objetos que se usan en múltiples pantallas. @StateObject y @EnvironmentObject están diseñados para estos propósitos. Además, @State no es adecuado para almacenar grandes cantidades de datos — cada cambio redibujará toda la vista.

@State y @Binding: trabajo conjunto

@Binding es un puente entre @State en una vista padre y una vista hija que necesita modificar ese estado. El padre declara @State, y el componente hijo recibe un Binding a través de la proyección $. Cambiar el Binding en la vista hija actualiza automáticamente el @State en el padre — y viceversa. Esto garantiza un flujo de datos unidireccional con capacidad de retroalimentación.

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)
    }
}

En el listado, ParentView posee el @State text, y ChildView recibe $text como Binding. El TextField dentro de ChildView se vincula a este Binding mediante text: $text. Cuando el usuario escribe en el TextField, el valor cambia en ChildView a través del Binding, lo que provoca una actualización de @State en ParentView. Ambas vistas se redibujan con el nuevo valor.

Errores típicos al trabajar con @State

El error más común es asignar una clase a una propiedad @State. Si escribes @State var model = MyClass(), SwiftUI no podrá rastrear cambios en las propiedades dentro de la clase — solo el reemplazo del objeto. Para clases, usa siempre @StateObject. El segundo problema común es declarar @State sin el modificador private, lo que viola el principio de encapsulación del estado.

Pasar @State directamente a una vista hija sin $ es otro error típico. Si pasas TextField(text: text) en lugar de TextField(text: $text), el componente hijo recibe solo una cadena, no un Binding. Los cambios de texto en el TextField no se sincronizarán con el @State del padre. Usa siempre la proyección $ para pasar Binding.

El tercer error son múltiples propiedades @State para datos relacionados. Si varios valores forman lógicamente un todo único (por ejemplo, campos de formulario), combínalos en una sola estructura con un único @State. Esto simplifica el paso de estado a las vistas hijas y reduce el número de desencadenantes de actualización individuales.

Ejemplos de uso de @State en SwiftUI

@State se utiliza en la mayoría de los proyectos SwiftUI para la interactividad básica. Consideremos un ejemplo de formulario de inicio de sesión donde @State gestiona los campos de texto y el estado de carga. Este patrón aparece en cada aplicación — desde notas simples hasta soluciones empresariales complejas.

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("Iniciar sesión") {
                login()
            }.disabled(isLoading)
        }
    }

    private func login() {
        isLoading = true
        // Realizar solicitud de red
    }
}

En el ejemplo, hay cuatro propiedades @State: email y password para los campos del formulario, isLoading para la indicación de carga, y errorMessage para mostrar errores. Cada propiedad gestiona independientemente su parte de la interfaz. Cuando isLoading cambia, el botón se desactiva automáticamente mediante disabled(isLoading) — sin actualización manual de la UI.

Preguntas frecuentes

¿Por qué @State se declara con private?

@State está diseñado para el estado local de una vista específica. El modificador private garantiza que otros componentes no puedan cambiarlo directamente, rompiendo la encapsulación. Para acceso externo, usa la proyección $.

¿Puede @State contener un array o diccionario?

Sí, @State admite arrays y diccionarios ya que son tipos de valor. Sin embargo, cuando cambia un elemento de un array, SwiftUI redibuja toda la vista. Para listas grandes, @StateObject con @Published es más eficiente.

¿Qué sucede cuando se asigna nil a una propiedad @State con tipo Optional?

@State funciona correctamente con tipos Optional. Cuando se asigna nil, SwiftUI detecta el cambio y redibuja la vista. Esto es conveniente para estados como errorMessage: String?, donde nil significa que no hay error.

¿Cómo se comporta @State cuando la vista reaparece?

@State conserva el valor mientras la vista permanezca en la jerarquía. Si la vista se elimina de la jerarquía y se añade de nuevo, @State se reinicializa con el valor por defecto. Para persistencia, usa @AppStorage.

¿Se pueden animar los cambios de @State?

Sí, envuelve el cambio en withAnimation: withAnimation(.easeInOut) { isExpanded.toggle() }. SwiftUI anima la transición entre el estado antiguo y nuevo de la interfaz con el tipo de animación especificado.

Resumen

  • @State — Property Wrapper para estado local de una sola vista, actualizando automáticamente la interfaz
  • Funciona con tipos simples: String, Int, Bool, así como structs y enums
  • No funciona con tipos de referencia (clases) — usa @StateObject
  • Siempre private — el estado no debe cambiarse desde fuera directamente
  • Proyección $ — crea un Binding para pasar derechos de cambio a vistas hijas
  • Múltiples @State en una vista — práctica normal para estados independientes
  • withAnimation — permite animar cambios en propiedades @State

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