Estado y property wrappers en SwiftUI — repaso rápido
Comparativa práctica de @State, @Binding, ObservableObject clásico y el sistema moderno Observation.
¿Quién es el propietario del estado?
Empieza por identificar quién crea y conserva el valor. La vista propietaria gestiona su ciclo de vida, mientras que las vistas hijas pueden recibir bindings o dependencias observables.
| Wrapper o macro | Propiedad del estado | Uso habitual |
|---|---|---|
| @State | Estado local retenido por la vista. | Valores simples o modelos @Observable creados por esa vista. |
| @Binding | Conexión de lectura y escritura a un estado externo. | Una vista hija modifica el estado del padre. |
| @StateObject | La vista crea y conserva un ObservableObject clásico. | Modelo con ciclo de vida propio usando el sistema anterior. |
| @ObservedObject | La vista observa un ObservableObject creado fuera. | Inyección del modelo desde el padre. |
| @EnvironmentObject | ObservableObject compartido en el árbol de vistas. | Dependencias de UI compartidas; usar con criterio. |
| @Observable | Macro de Observation para detectar acceso a propiedades. | Modelos observables modernos sin @Published. |
| @Bindable | Ofrece bindings sobre propiedades de @Observable. | TextField y otros controles que editan propiedades. |
Regla mental para la entrevista
Con Observation moderno, @State puede poseer un modelo @Observable, mientras que @Bindable ofrece bindings para editar sus propiedades. En el sistema clásico, @StateObject es para la instancia creada y poseída por la vista, y @ObservedObject para objetos externos.
import SwiftUI
import Observation
@Observable
final class LoginForm {
var email = ""
var password = ""
}
struct LoginView: View {
@State private var form = LoginForm()
var body: some View {
LoginFields(form: form)
}
}
struct LoginFields: View {
@Bindable var form: LoginForm
var body: some View {
TextField("Email", text: $form.email)
}
}Environment, ciclo de vida y flujo de datos
@Environment proporciona dependencias del entorno. @EnvironmentObject pertenece al sistema clásico ObservableObject; con Observation puedes inyectar modelos @Observable por su tipo a través del environment. @State representa estado transitorio de UI, no almacenamiento persistente.
import SwiftUI
import Observation
@Observable
final class Session {
var username = "Guest"
}
struct RootView: View {
@State private var session = Session()
var body: some View {
ProfileView().environment(session)
}
}
struct ProfileView: View {
@Environment(Session.self) private var session
var body: some View {
Text(session.username)
}
}Regla: si la vista hija solo lee un modelo @Observable, basta con recibir su referencia; usa @Bindable cuando un control necesite un binding. @StateObject y @ObservedObject siguen siendo adecuados con ObservableObject/@Published, no para aplicar indiscriminadamente a @Observable.
Errores y trade-offs
Evita crear modelos costosos repetidamente, sitúa el estado en el propietario común mínimo y no confundas @State con persistencia. Observation requiere iOS 17 o posterior, así que valora alternativas según el deployment target.
Notas personales de estudio. Verifica los matices según la versión de Swift/iOS y la documentación oficial.