2011-10-24 13 views
12

Disculpe, no estoy seguro del idioma correcto aquí, pero cuando se llaman a métodos porque son métodos de delegado o métodos llamados como resultado de ser enumerados como el objetivo de un observador, se ejecutan en el hilo principal ?iOS ¿Los métodos invocados por los delegados y observadores se ejecutan en el hilo principal?

me pregunto si puedo realizar cambios en la interfaz de usuario en estos métodos, o tengo que envolverlos en

dispatch_async(dispatch_get_main_queue(), ^{ UI stuff }); 

TIA: John

Respuesta

9

Para los delegados que esto puede variar. Si la documentación no especifica, generalmente se envían en el hilo principal. Tradicionalmente, UIKit se debe utilizar en el hilo principal, por lo que a los delegados casi siempre se les llamará desde el hilo principal.

Para notificaciones Creo que quieres este pequeño recorte.

Un centro de notificaciones entrega notificaciones a los observadores de forma síncrona. En otras palabras, los métodos postNotification: no regresan hasta que todos los observadores hayan recibido y procesado la notificación. Para enviar notificaciones de forma asincrónica, use NSNotificationQueue. En una aplicación multiproceso, las notificaciones se entregan siempre en el hilo en el que se publicó la notificación, que puede no ser el mismo hilo en el que se registró un observador.

De http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/nsnotificationcenter_Class/Reference/Reference.html

Y, finalmente, para MVA, las notificaciones pueden venir de otros hilos. Esto es lo que un ingeniero de Apple tuvo que decir sobre su manejo.

http://lists.apple.com/archives/cocoa-dev/2007/May/msg00022.html

+0

También para NSURLConnection las devoluciones de llamadas de delegados están en la secuencia que inició la operación de carga asíncrona, que no tiene por qué ser el hilo principal. – progrmr

+1

Seguramente estaría bien si los documentos dejaran esto en claro, pero por ejemplo, UIImagePickerControllerDelegate Protocol Reference ni siquiera usa la palabra 'thread'. No he visto ningún problema con imagePickerController: didFinishPickingMediaWithInfo :, pero de repente me he vuelto más consciente de los problemas de subprocesos. Tu recorte fue definitivamente útil para las notificaciones, que uso en mi aplicación. Una vez más, mi nuevo conocimiento de hilos me hizo pensar en ellos. Tendré que revisarlos todos para asegurarme de que todos sean correctos. ¡Gracias! – John

+0

Puede suponer que con los objetos de la interfaz de usuario los delegados siempre están en el hilo principal. Los documentos especificarán si hay una excepción, que nunca he visto. Puede inferir esto de los documentos aquí. http://developer.apple.com/library/ios/documentation/uikit/reference/uiview_class/UIView/UIView.html#//apple_ref/doc/uid/TP40006816-CH3-SW147 – logancautrell

8

Como se ha indicado, el hilo variará en función de la persona que llama. En el método de delegado, si es necesario para adaptarse, siempre se puede hacer algo como esto:

if ([NSThread isMainThread]) { 
    // do the UI stuff as normal 
} else { 
    dispatch_async(dispatch_get_main_queue(), ^{ UI stuff }); 
} 
+0

¿Cuál será la diferencia si no verifico el hilo actual y siempre lo envío de forma asíncrona? Entonces, incluso si se llama a ese método de delegado en el hilo principal, lo enviaré, ¿cuáles son los inconvenientes de esto? ¿O cuáles son los pros de esta solución (verificando el hilo actual)? –

+1

No creo que haya ningún daño al hacer el dispatch_async, incluso si ya está en el hilo principal. Tendría que experimentar para asegurarse de que la penalización de rendimiento del método dispatch_async no sería mucho peor que comprobar la propiedad NSThread isMainThread. –

3

La idea básica es que en todos los casos el método de observador o el delegado se denominan en el mismo hilo de la notificación inicial (por el patrón del observador) o el código de delegación se están ejecutando, por lo que si no está seguro de que se recomienda enviar su bloque de IU en el hilo principal. Trataré de justificar estas declaraciones en el siguiente razonamiento, por supuesto que puedo estar equivocado.

A menos que se especifique explícitamente en la documentación del protocolo delegado, en el patrón delegado se llama directamente a un método en el mismo hilo que la persona que llama se está ejecutando en el momento de la llamada. P.ej. Si la persona que llama (objeto delegar) quiere llamar a su delegado y actualmente se está ejecutando en "Tema-1", entonces la llamada va a ocurrir en el mismo hilo:


// this is running in "Thread-1" --> then aDelegateMethod will continue on "Thread-1" 
[myDelegate aDelegateMethod] 

En cuanto al patrón de observador, no lo vea cualquier razón válida para que el sistema envíe una notificación de observación explícitamente en el hilo principal, especialmente si el cambio de valor original que origina la notificación se está ejecutando en otro hilo. De hecho, en el caso de KVO, el tiempo de ejecución cambia la definición de clase al agregar algunos métodos privados que anulan los métodos de establecimiento para hacer las notificaciones, y no veo una razón válida para hacer esta llamada explícitamente en el hilo principal. Entonces, según yo, una notificación de KVO puede originarse desde cualquier hilo y este hilo es el mismo que está ejecutando el cambio de valor en la clase observada.

Finalmente, el mecanismo basado en NSNotificationCenter ve sus notificaciones llamadas por el mismo hilo donde se ha publicado la notificación original. Esto está claramente establecido en la documentación de Apple (y vale la pena decir que cada hilo tiene su propia cola de notificaciones).

Por lo tanto, en todos los casos, el hilo se mantiene y si quiere asegurarse de que su bloque UI se llame en la cola principal, utilice la llamada GCD que publicó en su pregunta.

+0

Re su última frase: esta parece ser la forma más directa para tratar el problema. Acabo de revisar mi código y me aseguré de hacerlo en todos los casos. Me encontré con el problema porque mi aplicación crea un video en un hilo de fondo. Quise deshabilitar un botón en mi UI mientras se creaba el video, pero esto causó cierto comportamiento de disgusto. Eso, a su vez, condujo a mi nueva conciencia sobre problemas de enhebrado :-) – John

Cuestiones relacionadas