¿Cómo hacer un acoplamiento rígido entre los cambios de datos del model conetworkingata / NSManagedObject con la interfaz de usuario de las aplicaciones?

TL; DR: para simplificar toda la descripción, cómo implementar una interfaz de usuario de control de vista no basada en tablas, cuando las properties del object de datos principales se actualizan frecuentemente en segundo plano. Y con eso, la representación visual de los datos debe actualizarse de inmediato. [En tableview es muy fácil de manejar, usa un FRC y simplemente vuelve a cargar la fila cuando se actualiza el object, a través de los methods de delegación de FRC.]


Sé sobre NSFetchedResultsController y la asignación a través de eso a una interfaz de usuario. Pero eso es solo cuando la interfaz de usuario está basada en lists.

En mi caso, varios hardware de tipo similar están conectados a mi aplicación a través de bluetooth (BLE), y cada uno normalmente proporciona actualizaciones con una frecuencia de 1 segundo en general. Por ejemplo, temperatura, cambios de carga.

Entonces, aquí hay un ejemplo del flujo de UI,

Lista -> detalles

Detalles

  1. Salud
  2. Actividad
  3. Notificación de configuration

Los detalles solo representan una información relacionada con el hardware (número de serie, versión de firmware, date de fabricación, etc.), y tiene 3 botones nombrados anteriormente, que cuando son tocados empujan a los respectivos controlleres.

El model Entity también está diseñado en consecuencia, aquí hay una mirada, tengo una entidad primaria, digamos ABC . Entonces, ABC tiene una relación de uno a uno con otras entidades como HealthDetails , Activity , NotificationSetting y HardwareDetails . ABC tiene pocos attributes como identifier , connected , name , etc.

ListViewController es un UITableViewController y, por lo tanto, estoy usando un NSFetchedResultsController . Ahora restante todos los otros controlleres de vista son solo controlleres de vista normal, con solo las tags de Título como 'última date cargada', que es estática y una 'label de descripción' debajo de ella que muestra los datos. Otros controlleres de vista también se llenan de manera similar con solo botones, tags, etc.

Actualizar el controller de vista de list es fácil con NSFetchedResultsController .

[Cuando el usuario usa una fila / celda, solo obtengo el object utilizando la ruta de índice desde FRC e inyecto en el controller de vista de destino.]

Sin embargo, los otros controlleres de vista no están basados ​​en la vista de tabla. Por lo tanto, estoy usando la notificación para controlar otras actualizaciones de UI del controller de vista.

Por ejemplo, cuando mi BluetoothManager recibe una actualización del hardware con respecto a una característica, canalizo la identificación característica y los datos a mi DatabaseHelper , que luego decodifica los datos y se inserta en el object administrado respectivo, y en este momento solo disparo una notificación con el identificador del object que se actualizó.

Todos los UIViewController s en la jerarquía que se encuentran en la stack de navigation están suscritos como observadores. Y si el identificador de la notificación coincide con el object de entidad que se muestra actualmente, actualizo la interfaz de usuario. Actualmente todo esto funciona bien.

Pero, siento que es muy torpe, manejando muchas notifications. ¿Es esta la única forma o existen mejores methods existentes para acoplar de manera estrecha los models de datos centrales individuales a las UI?


Veo algunos comentarios que sugieren manejar solo a través de FRC, pero no estoy seguro de si FRC se puede usar en una representación de interfaz de usuario no basada en tabla. He buscado y no he encontrado mucho. Si alguien conoce algún tutorial / blog con una descripción teórica que sería de gran ayuda.

Otra cosa, las sugerencias sobre FRC para manejar todo, no lo obtuve por completo, ¿tengo que colocar un controller FRC por vista? ¿No hay otra forma?

No debes perder nada. El delegado en el NSFetchedResultsController le informará cuando se actualice algo. Si tiene una interfaz de usuario visible, su interfaz de usuario se actualizará. Si no tiene una interfaz de usuario visible, o no la quiere, puede vincularla a su subclass específica de NSManagedObject para get los detalles de salud y, a continuación, tomar cualquier acción que sea apropiada en function del hecho de que algo haya cambiado.

Dependiendo de lo que esté haciendo, puede ser tan simple como implementar controllerDidChangeContent(_:)

Si eso no responde a su preocupación, tendrá que proporcionar más detalles sobre cuál es el problema específico.

Mencionaste cambiar "ViewControllers", así que asumo cuando presionas como dijiste en los comentarios "Lista> Salud> Actividad> Configuración" que cada una de estas son classs de UIViewController , ¿verdad? Si es así, implementa el método viewWillAppear en cada uno de estos, y asegúrate de hacer allí toda la initialization de la interfaz de usuario. Al hacerlo, usted garantiza que cuando ocurra el pop, se llamará a este método y su UI se actualizará (b / c tiene la lógica ahora en este método para hacer la actualización). Solía ​​inicializar la interfaz de usuario en viewDidLoad pero tenía el mismo problema que ahora. viewWillAppear a viewWillAppear fue la solución en mi situación.

Después de esto, si aún no está viendo los valores correctos en la interfaz de usuario, coloque los puntos de interrupción en el método viewWillAppear e inspeccione los datos que están en su model. Tal vez el model sea incorrecto, en cuyo caso, quizás haga una consulta (búsqueda) para get lo que necesita nuevamente. Esto no debería ser un problema a less que use contexts padre / hijo y no cometa cambios de context secundarios al padre.

Pero siento que es muy torpe, manejando muchas notifications. Es la única forma o methods mejores que existe para acoplar de manera estrecha los models de datos centrales individuales a las UI.

Sinceramente, no creo que haya un model mejor, ya que no estás usando FRC en las otras vistas. Y si no está utilizando vistas de tabla para volver a cargar o get nuevos datos, definitivamente no necesita usar FRC (aunque no iré tan lejos para decir que no debería hacerlo porque no puedo respaldarlo firmemente )

Utilizo este model exacto en mi request, que tiene varias vistas diferentes que reciben la notificación a través de observadores, al igual que lo que está haciendo. Si esto no funciona bien, hay otra opción a considerar.

Lo siento, no tengo suficiente reputación para agregar comentarios.

Me uniré a otros que sugieren usar FRC. No puedo ayudarte con el blog / tutorial, pero CoreStore ObjectMonitor es un muy buen ejemplo para que se pueda usar en contexts diferentes (sin tableview). Estoy seguro de que no será un problema para que lo consigas.

Entonces ya tiene una solución a su problema, usando notifications. No hay nada explícitamente mal con eso. Podría mejorarse observando solo la ID en la que está interesado VC, para evitar que múltiples VC procesen y comprueben si la notificación se aplica a ellos. Esta es una solución útil.

Un FRC es fácil de usar con un layout basado en tabla / cuadrícula pero eso no es todo lo que es bueno, ya que ofrece observación de context específica. En su nivel más alto, esto significa responder solo a controllerDidChangeContent: delegar callback para actualizar la interfaz de usuario. Esto generalmente es mejor que su notificación porque es específica, aunque es un poco más costosa en términos de consumo de memory (esto es tan importante como irrelevante).

Si sus VC de detalle muestran múltiples piezas de información, es posible que no esté utilizando una vista de tabla / colección, pero todavía hay un layout de estilo de list / rejilla y las routes de índice de FRC podrían significar algo relacionado con eso.

El suplente que no se ha discutido es KVO, que es soportado de forma nativa por todos los objects administrados. Esta es la solución más adecuada para usted porque se le pasa el object y, como resultado, no necesita realizar ninguna observación de nivel superior / context. Trabajar directamente con KVO es un poco molesto a veces, así que quieres usar alguna biblioteca de ayuda, como esta , para que puedas usar bloques para lidiar con los artículos específicamente actualizados.

Al usar KVO, se obtiene el data binding, por lo que una actualización de los datos del model subyacente se refleja directamente en su interfaz de usuario como resultado de la callback de observación detallada.

En primer lugar, entiendo sus preocupaciones sobre el uso de un patrón para esto. (Solo para el protocolo: no es un patrón uno a uno, porque un delegado puede ser un delegado de muchas classs delegadas. En realidad, eso sucede).

El patrón to-many es de hecho notifications: está transmitiendo. Pero no entiendo, ¿por qué tienes muchas notifications? Simplemente escuche el context NSManagedObjectContextDidSaveNotification , que le dará una list de objects modificados. Debería ser fácil para el controller de vista de detalle recoger el object que muestra.

¿Te malinterpreté?