Estado: @State y @Binding
SwiftUI redibuja la interfaz cuando el estado cambia. Domina @State (ahora una macro en iOS 26) y @Binding para conexiones de dos vías entre vistas.
Aquí SwiftUI cobra vida. El estado es el dato que, al cambiar, hace que la interfaz se actualice sola. No mueves elementos a mano: cambias un valor, y SwiftUI redibuja lo que dependa de él. Entender el flujo de datos es entender SwiftUI.
- Qué es una “fuente de la verdad”.
@Statepara el estado propio de una vista.@Bindingpara conexiones de dos vías.- El flujo de datos que hace reactiva la UI.
La idea central: estado → UI
SwiftUI mantiene una regla: la interfaz es una función del estado. Cuando el estado cambia, la vista se recalcula. Tú no tocas la pantalla; tocas el dato.
struct Contador: View {
@State private var cuenta = 0
var body: some View {
VStack {
Text("Cuenta: \(cuenta)")
Button("Sumar") { cuenta += 1 }
}
}
}
Al pulsar el botón, cuenta cambia y SwiftUI vuelve a llamar a body — el Text muestra el nuevo valor. Automático.
@State: el estado propio de la vista
@State marca un dato que pertenece a esa vista y que, al cambiar, la redibuja. Úsalo para estado simple y local (un contador, un texto de un campo, si un toggle está activo):
@State private var texto = ""
@State private var activo = false
Novedad 2026: @State pasó a ser una macro que inicializa el valor de forma perezosa, solo una vez, en lugar de recrearlo en cada reinicialización de la vista. En la práctica no cambias cómo lo escribes, pero ganas rendimiento gratis, sobre todo con objetos @Observable (Nivel 3). Márcalo siempre private: el estado propio no debería tocarse desde fuera.
@Binding: una conexión de dos vías
Cuando una vista hija necesita leer y escribir un estado que vive en el padre, usas @Binding. Es una referencia al estado, no una copia:
struct Interruptor: View {
@Binding var encendido: Bool // conexión al estado del padre
var body: some View {
Toggle("Encendido", isOn: $encendido)
}
}
struct Panel: View {
@State private var luz = false // la fuente de la verdad
var body: some View {
VStack {
Interruptor(encendido: $luz) // pasa el binding con $
Text(luz ? "💡 encendida" : "🌑 apagada")
}
}
}
Fíjate en el $: luz es el valor (un Bool), pero $luz es el binding (la conexión de dos vías a ese valor). Cuando un componente pide un Binding —como Toggle(isOn:) o TextField(text:)—, le pasas $algo. El hijo lo modifica y el cambio sube solo al padre, que redibuja. Una única fuente de la verdad, muchas vistas conectadas a ella. Este patrón —estado arriba, bindings hacia abajo— es la columna vertebral de toda app SwiftUI.
Bindings con componentes del sistema
Muchos controles piden un binding para reflejar y cambiar el estado:
@State private var nombre = ""
@State private var volumen = 0.5
TextField("Tu nombre", text: $nombre)
Slider(value: $volumen)
Toggle("Notificaciones", isOn: $activo)
Escribes en el TextField y nombre se actualiza; mueves el Slider y volumen cambia. Sin código de “cuando cambie, actualiza”: el binding lo hace.
@State es para estado simple y local de una vista (tipos de valor: Bool, String, Int, structs pequeñas). Para modelos de datos compartidos entre varias vistas, o lógica compleja, usarás clases @Observable (Nivel 3). Regla rápida: dato local y simple → @State; modelo compartido → @Observable.
- Crea un contador con
@Statey dos botones (+ y −). - Añade un
TextFieldcon@Statey muestra abajo lo que escribes en vivo. - Crea una vista hija con
@Binding vary pásale$algodesde el padre. - Usa un
Toggle(isOn: $...)en el hijo y muestra el estado en el padre. - Observa que solo cambias valores: nunca “actualizas la pantalla” a mano.