Back home

SwiftUI Series 04 | Gestión de estado de SwiftUI: selección de @State, @Binding, @ObservedObject, @StateObject

La verdadera clave es responder primero "¿Quién posee estos datos y quién impulsa los cambios en la interfaz?"

El lugar donde es más probable que las personas se queden “atascadas” en SwiftUI es el estado.

Las preguntas más habituales suelen ser estas:

  • ¿Deberíamos utilizar @State o @Binding para este valor?
  • ViewModel se inicializará repetidamente
  • ¿Por qué la subvista no puede cambiar los datos de la vista principal?
  • El valor obviamente ha cambiado, pero la página no se actualiza como se esperaba.

Si solo confía en memorizar los envoltorios de atributos para estos problemas, es fácil confundirse cada vez más. Porque la verdadera causa raíz suele ser:

Sin antes pensar claramente en “¿quién es el dueño de este estado?”

1. No te apresures a elegir un envoltorio. Primero pregunte: ¿De quién son los datos que tiene?

Ésta es la pregunta más importante.

En SwiftUI, cada vez que vea un valor de estado, pregúntese:

  • ¿Este valor pertenece a la Vista actual?
  • La vista principal todavía es propietaria y la subvista simplemente se toma prestada y se modifica.
  • Aún pertenece a un objeto externo, la Vista actual solo está observando

Una vez que se responda claramente a esta pregunta, muchas opciones de contenedor surgirán de forma natural. Por el contrario, si omite este paso y pregunta directamente “cuál se usa comúnmente en este escenario”, será fácil acumular código mediante prueba y error.

2. @State es realmente adecuado para “el propio estado local de la Vista actual”

@State es más adecuado para:

Este estado sólo pertenece a la Vista actual. La existencia local, el consumo local y abandonar esta visión básicamente no tienen sentido.

Por ejemplo:

  • El contenido actual del cuadro de entrada.
  • Ya sea para mostrar la hoja
  • Un cierto estado parcialmente expandido y colapsado
  • Selección de pestaña actual

Lo que estos estados tienen en común es:

  • Propiedad clara
  • El ciclo de vida está fuertemente ligado a esta Vista.
  • No vale la pena actualizar al estado de empresa externa

Si un fragmento de estado no tiene sentido fuera de la Vista actual, generalmente es una buena opción para @State.

3. El punto clave de @Binding es que “la propiedad no ha cambiado, pero se ha prestado el permiso de escritura”

Una situación común es entender @Binding como “las subvistas también pueden cambiar el valor de la vista principal”. Esta comprensión no es errónea, pero no es lo suficientemente precisa.

Es más:

  • Este estado todavía pertenece a la vista principal.
  • la subvista no es propietaria
  • La subvista solo obtiene los canales de lectura y escritura.

Este asunto es fundamental porque determina si se conserva la atribución de datos correcta cuando se califica el componente.

Es decir:

  • @State es “mío”
  • @Binding “sigue siendo el mismo, pero estoy autorizado a cambiarlo”

Una vez entendido en términos de propiedad, @Binding ya no puede confundirse con una “solución única para compartir datos”.

4. @ObservedObject y @StateObject se confunden más fácilmente porque la gente suele mezclar “observación” y “posesión”

El mal uso más común de estos dos envoltorios proviene esencialmente del mismo problema:

No está claro si “la Vista actual observa un objeto externo” o “la Vista actual crea y sostiene de manera estable este objeto”.

@ObservedObject

Es mejor expresar:

  • Este objeto se pasa desde el exterior.
  • La Vista actual simplemente lo observa.
  • La Vista actual no es responsable de crearla ni de mantenerla de manera estable.

@StateObject

Es mejor expresar:

  • La Vista actual crea este objeto por sí misma.
  • y desea mantenerlo estable durante la actualización de la vista

La diferencia fundamental entre los dos no es “cuál es más avanzado”, sino más bien:

  • quién creó el objeto
  • ¿Quién es responsable del ciclo de vida del objeto?

Esto también muestra que muchos problemas de inicialización repetida de ViewModel son esencialmente propiedad de objetos fuera de lugar.

5. Un juicio de ingeniería muy práctico: el estado de la interfaz de usuario local y el estado del negocio deben considerarse por separado

El estado de muchas páginas será confuso y el estado de diferentes niveles se agrupará en una bola.

Por ejemplo, una página puede contener:

  • Contenido del cuadro de entrada
  • Filtrar si la ventana emergente está abierta
  • Resultados de la solicitud de red
  • Estado de carga de la página
  • Lista de objetos comerciales

Estos valores parecen denominarse “estado”, pero no son el mismo tipo de estado.

Normalmente lo divido aproximadamente en dos categorías:

1. Estado de la interfaz de usuario local

Por ejemplo:

  • Ya sea para expandirse
  • Contenido de entrada actual
  • Artículo seleccionado actualmente
  • Interruptor de visualización parcial

Este tipo de estado está más cerca de @State / @Binding.

2. Estado de los datos comerciales

Por ejemplo:

  • Información del usuario
  • Lista de datos
  • Proceso de carga
  • Error de solicitud

Este tipo de estado suele ubicarse mejor en un objeto observable externo o en un contenedor de estado de nivel superior.

Una vez que estos dos tipos de estados no se distinguen, la página tendrá fácilmente valores de paso de estado local, estado de ViewModel y capa principal. Al final, no está claro quién es el propietario.

6. Muchos problemas de “el valor ha cambiado pero la interfaz es incorrecta” se deben esencialmente a que los límites estatales se mezclan.

Una situación común es que:

  • Obviamente cambié el valor, pero ¿por qué la página no cambió como pensaba?

Por supuesto, a veces este es el envoltorio incorrecto, pero más a menudo:

  • El estado que debería ser propiedad de la capa principal lo mantiene temporalmente la capa secundaria.
  • Los objetos que deberían haber existido durante mucho tiempo se tratan como objetos de observación temporales.
  • El estado de la interfaz de usuario local y el estado del negocio se sobrescriben entre sí.

En otras palabras, lo que parece un “problema de actualización” suele ser en realidad un problema de propiedad.

Para muchos problemas de estado en SwiftUI, una vez que verifica “quién posee estos datos”, generalmente puede encontrar la causa raíz más rápido que mirar el fenómeno de la interfaz.

7. Un método de juicio simplificado que uso a menudo.

Aunque los proyectos reales serán más complicados, suelo utilizar este conjunto de juicios simples en el desarrollo diario:

1. ¿Es este el estado simple de la propia Vista actual?

Sí, dar prioridad a @State

2. ¿Es propiedad de la vista principal y simplemente la toma prestada y la modifica la subvista actual?

Sí, dar prioridad a @Binding

3. ¿Es este un objeto observable pasado desde el exterior?

Sí, dar prioridad a @ObservedObject

4. ¿Es este un objeto que creó la Vista actual y espera mantenerse estable?

Sí, dar prioridad a @StateObject

Este conjunto de sentencias ciertamente no cubre todos los detalles, pero es lo suficientemente práctico para una gran cantidad de páginas comerciales.

8. Conclusión: Lo primero que realmente debemos entender sobre la gestión estatal es la propiedad.

Para decirlo en forma más breve, diría:

En SwiftUI, lo más importante sobre la gestión del estado es preguntar primero “Quién es el propietario de estos datos y quién es responsable de hacer que la interfaz cambie con ellos”.

Una vez que la propiedad esté clara en primer lugar, muchas opciones de envoltorio surgirán de forma natural. Por otro lado, si no piensa claramente acerca de la propiedad y se familiariza con la API más adelante, será fácil escribir una página que “se ejecute pero se vuelva cada vez más desordenada”.

FAQ

What to read next

Related

Continue reading