Saltar al contenido

@Observable y el estado compartido

El framework Observation reemplaza a ObservableObject: clases reactivas con la macro @Observable, sin @Published ni boilerplate. El corazón del estado moderno en SwiftUI.

@State es genial para datos locales, pero las apps reales necesitan modelos compartidos entre muchas vistas: un carrito, la sesión del usuario, los ajustes. Para eso llegó el framework Observation con la macro @Observable: reactividad sin ceremonia.

  • La macro @Observable y qué genera.
  • Usar un modelo observable en las vistas.
  • @Bindable para bindings a sus propiedades.
  • Por qué reemplazó a ObservableObject.

El modelo observable

Marca una clase con @Observable y SwiftUI observará automáticamente cualquier propiedad que uses en una vista:

SWIFT
import Observation@Observableclass CarritoModel {    var items: [String] = []    var total = 0.0    func añadir(_ item: String, precio: Double) {        items.append(item)        total += precio    }}

Sin @Published, sin objectWillChange, sin nada. SwiftUI detecta qué propiedades lee cada vista y solo la redibuja cuando esas cambian.

Usarlo en una vista

La vista que “posee” el modelo lo guarda en @State (sí, @State también sirve para objetos observables):

SWIFT
struct TiendaView: View {    @State private var carrito = CarritoModel()    var body: some View {        VStack {            Text("Total: \(carrito.total, format: .currency(code: "EUR"))")            Button("Añadir café") {                carrito.añadir("Café", precio: 1.5)            }        }    }}

Cambias carrito.total desde el método y la vista se actualiza sola.

Observación granular = rendimiento

La magia de @Observable: SwiftUI rastrea qué propiedades lee de verdad cada vista. Si una vista solo muestra carrito.total, cambiar carrito.items no la redibuja. Con el viejo ObservableObject + @Published, cualquier cambio en el objeto redibujaba todo lo suscrito. Ahora la actualización es quirúrgica: solo se recalcula lo que depende del dato que cambió. Modelos grandes sin penalización de rendimiento.

@Bindable: bindings a un modelo

¿Necesitas un TextField o Toggle conectado a una propiedad del modelo? @Bindable te da los $bindings:

SWIFT
struct AjustesView: View {    @Bindable var ajustes: AjustesModel    var body: some View {        Form {            TextField("Nombre", text: $ajustes.nombre)     // $ del modelo            Toggle("Modo oscuro", isOn: $ajustes.oscuro)        }    }}

@Bindable es el puente entre un objeto @Observable y los controles que piden un Binding.

Adiós a ObservableObject

Si ves código con class X: ObservableObject, @Published var, @StateObject y @ObservedObject, es el sistema anterior. La tabla de equivalencias:

Antiguo Moderno (Observation)
class: ObservableObject @Observable class
@Published var var (normal)
@StateObject var @State var
@ObservedObject var var o @Bindable var
@EnvironmentObject @Environment(Modelo.self)

Empieza siempre con @Observable

Para cualquier proyecto nuevo con iOS 17+, usa @Observable desde el principio: menos código, mejor rendimiento y es el camino que Apple recomienda. El sistema antiguo solo lo verás en código heredado. La comunicación entre vistas mediante @Environment la ves en la próxima lección.

Comparte estado de verdad

  1. Crea una clase @Observable con una propiedad y un método que la cambie.
  2. Posee el modelo en una vista con @State private var.
  3. Muestra una propiedad y un botón que llame al método; observa la actualización.
  4. Crea otra vista con @Bindable y conecta un TextField a $modelo.propiedad.