ios - ultima - WatchOS: ¿Se deberían llamar las actualizaciones de la interfaz de usuario desde la extensión en el hilo principal?
ultima actualizacion apple watch (3)
Para las aplicaciones iOS, la actualización de la interfaz de usuario se realiza exclusivamente desde el subproceso principal; no se recomienda hacerlo, lo que puede provocar un comportamiento inesperado.
En watchOS, el sistema operativo está estructurado con una extensión de reloj y una aplicación, como ''contenedores'' diferentes. Por lo general, las actualizaciones de la interfaz de usuario se llaman desde la extensión y éstas actualizan algo en el contenedor de la aplicación.
¿Se aplica la misma lógica de hilo principal a la actualización de la interfaz de usuario desde la extensión del reloj, o se pueden llamar actualizaciones de la interfaz de usuario desde el fondo?
Editar - para aportar algo de claridad . Desde el contenedor de la aplicación, las actualizaciones de la interfaz de usuario probablemente deberían ocurrir en el subproceso principal (como sucede en la mayoría de los sistemas / sistemas operativos, como se indica a continuación). La pregunta realmente es si watchOS maneja eso por nosotros, es decir, si llamar a una actualización de UI en el hilo de fondo de la extensión se publicará automáticamente en el hilo principal del contenedor de la aplicación para nosotros.
Después de contactar a Apple a través de un Incidente de soporte técnico, la respuesta y la explicación recibidas se encuentran a continuación.
TLDR: usar el hilo principal.
Todas las actualizaciones deben hacerse desde el hilo principal. Esta siempre ha sido la recomendación general para UIKit y esa recomendación se extiende a watchOS.
Podría ser útil comprender la razón subyacente de este requisito. Tenga en cuenta que, incluso con un canal de comunicación centralizado para serializar los cambios, surgen muchos problemas cuando intenta manipular el estado de la interfaz de usuario desde subprocesos en segundo plano. Por ejemplo, si bien el canal de serialización puede evitar que varios comandos de UI intenten ejecutarse simultáneamente, no puede controlar el orden en que se ejecutarán los comandos no relacionados. Considere los siguientes 2 bloques:
block 1 { DoUIChange1 DoUIChange2 } block 2 { DoUIChange3 DoUIChange4 }
Si ambos bloques se ejecutan en el hilo principal, entonces el flujo de comandos real es:
DoUIChange1 DoUIChange2 DoUIChange3 DoUIChange4
o…
DoUIChange3 DoUIChange4 DoUIChange1 DoUIChange2
Sin embargo, si ambos bloques se ejecutan en sus propios hilos, se abren aún más posibilidades:
DoUIChange3 DoUIChange1 DoUIChange2 DoUIChange4
o..
DoUIChange1 DoUIChange3 DoUIChange2 DoUIChange4
o..
DoUIChange1 DoUIChange3 DoUIChange4 DoUIChange2
etc ...
No hace falta decir que si el código de la interfaz de usuario es complejo, el número de combinaciones se convierte rápidamente en enorme, lo que hace que los errores inesperados de la interfaz de usuario sean prácticamente inevitables.
La Guía de programación de aplicaciones de Apple para watchOS probablemente sea la guía definitiva, pero no puedo encontrar ninguna referencia sobre cómo hacer actualizaciones de la interfaz de usuario en otros temas que no sean el tema principal.
Uno pensaría que si fuera importante que las actualizaciones de la interfaz de usuario se llamaran desde el subproceso principal, que lo declararía explícitamente en alguna parte (como lo hace en la Guía de programación de aplicaciones para iOS , en la sección Subprocesos y concurrencia ):
El trabajo que involucra vistas, Core Animation y muchas otras clases de UIKit generalmente debe ocurrir en el hilo principal de la aplicación. Hay algunas excepciones a esta regla, por ejemplo, las manipulaciones basadas en imágenes a menudo pueden ocurrir en subprocesos en segundo plano, pero en caso de duda, asuma que el trabajo debe ocurrir en el subproceso principal.
Sin embargo, la cita anterior podría interpretarse como válida para las actualizaciones de IU para una extensión Watch, ya que se ejecuta en iOS.
Todo lo anterior para decir, no creo que haya documentación de Apple que indique una forma u otra.
Sin embargo, aquí hay otro punto de datos: el código de ejemplo de Lister de Apple ahora incluye una extensión WatchKit, y por mi breve estudio, parece estar enviando recuperaciones a una cola de fondo (ver ListInfo.swift: 34) y actualizando la interfaz de usuario devolviéndolo. a la cola principal (ListsInterfaceController.swift: 98). Incluso hay un comentario allí diciendo que está haciendo eso:
El método fetchInfoWithCompletionHandler (_ :) llama a su manejador de finalización en una cola en segundo plano, se envía de vuelta a la cola principal para realizar actualizaciones de IU.
Creo que en base a lo anterior, cometería un error al hacer actualizaciones en el subproceso principal, a menos que usted determine que hay desempeño u otras implicaciones de hacerlo.
Siempre debes hacer actualizaciones de la interfaz de usuario en el hilo principal. No hacerlo resultará en una representación más lenta de la interfaz de usuario o posibles bloqueos de la aplicación. Esto no es específico de iOS o watchOS, ya que prácticamente todos los lenguajes de programación (C #, Java, C ++, etc.) requieren que realice actualizaciones de la interfaz de usuario en el hilo principal.
En watchOS 1, lo que sugieres podría tener sentido ya que la extensión estaba en el iPhone y la interfaz de usuario en el reloj. En ese caso, la aplicación se ejecutó como dos procesos separados y "Es posible que" no haya tenido que enviar el subproceso principal para las actualizaciones de la interfaz de usuario. Pero en watchOS 2 es diferente. Aunque la extensión watchU y la interfaz de usuario tienen diferentes objetivos, en watchOS 2 no se ejecutan como procesos separados en el reloj (puedes verificar esto viendo los procesos en ejecución en tu reloj Apple en Xcode y ver que solo hay uno para cada aplicación) . El hecho de que esté empaquetado como dos contenedores separados (e incluso se firmen de manera diferente) no significa que se ejecuten como dos procesos separados en el reloj.