Saltar al contenido →

@State, @ObjectBinding y @EnvironmentObject. ¿Qué son y cuándo usarlos?

SwiftUI, el nuevo framework para programar vistas en nuestras apps, introduce una nueva forma de coordinar los cambios en nuestro modelo de datos o variables con las vistas.

De esta forma cuando se produce un cambio en el modelo automáticamente la vista se actualiza para reflejar dicho cambio. Esto se hace en conjunción con el también nuevo framework Combine. Pero para esta introducción nos quedaremos con 3 conceptos. @State, @ObjectBinding y @EnvironmentObject.

Vamos a ver qué son y cuando y como usarlos.

@State

Recomendado para: Una variable atómica.
Alcance: Vista en la que está declarada.
Modificador de acceso recomendado: private

Cuando a una propiedad que declaramos en la estructura donde definimos nuestra View la calificamos como @State lo que estamos diciendo es que SwiftUI se va a encargar de monitorizar el estado de esa variable, y que si se produce algún cambio en ella, SwiftUI va a volver a recalcular la propiedad bodyde nuestra vista.

En resumen, que si se cambia la variable se vuelve a pintar la vista en la pantalla.

Podemos referinos a ella usando la forma habitual o anteponiendo $ al nombre de la variable.

En el ejemplo anterior declaramos un @State para la propiedad showResults que usaremos para mostrar la parte trasera de una tarjeta con la respuesta a una pregunta.

El cambio en el valor de la propiedad se produce al pulsar sobre la vista, gracias a la función handleFlipViewTap().

@ObjectBinding

Recomendado para: Una clase que representa una estrutura de datos.
Alcance: Vista en la que está declarada.
Modificador de acceso recomendado: private

En muchas de las vistas que conforman nuestras apps tenemos que mostrar información de alguna de las entidades que pueblan nuestro modelo de datos.

SwiftUI nos da una mecanismo por el que, al igual que con @State, podamos enlazar una de dichas entidades con lo que presentamos en nuestra vista y reaccionar ante los cambios producidos en el modelo.

Lo primero que tenemos que saber es que la clase que representa la entidad del modelo de datos tiene que ser eso, una clase ya que es obligatorio que implemente el protocolo BindableObject en cuya definición vemos que sólo se aplica a clases.

Este protocolo sólo necesita que implementemos la propiedad didChange cuyo valor debe ser un Publisher que usaremos para informar a SwiftUI de cualquier cambio que se produzca en el modelo.

En el siguiente código definimos un modelo de datos muy simple que consiste en una lista de versiones de macOS. Esta clase cumplimenta el protocolo BindableObject y se encarga de informar de los cambios en el modelo como se puede ver en la función add(_:)

La vista enlaza con el modelo mediante la propiedad marcada como @ObjectBinding

Cuando se pulsa sobre el botón se añade un nuevo sistema operativo al modelo y la vista se actualiza automáticamente.

@EnvironmentObject

Recomendado para: Una clase que representa una estrutura de datos.
Alcance: Todas las vistas de la app siempre y cuando el objeto se haya añadido el environemnt antes de mostrarla.

Hasta ahora todas las variables o clases sólo las usábamos en una vista en concreto, pero qué pasa si quiero que mi modelo esté disponible para todas las vistas de la app y que estén al tanto de los cambios que suceden.

Para este podemos usar los @EnvironmentObject, que se cargan en el Environment y desde ese momento están disponibles en las vistas de la app, de esta manera nos evitamos tener que pasar el modelo a cada vista en su inicializador.

Esto se hace mediante la función environmentObject(_:) que viene definida en el protocolo View.

En este caso se añade el modelo en el momento en el que se inicia la app para que así esté disponible para cualquier vista.

Ahora sólo nos queda usarlo en nuestras vistas, y en este caso tenemos que usar el property wrapper @EnvironmentObject

¡Un momento! Si no se lo pasamos como parámetro… ¿cómo lo encuentra? Pues porque se hace uso de otra las nuevas características que ha incorporado Swift, el Dynamic Member Lookup

Publicado en SwiftUI