2009-11-14 21 views
9

Me gustaría que se ejecute un método después de que haya pasado el método actual y se haya actualizado la UI. Para ese propósito, estoy usando [object performSelector:@selector(someSelector) withObject:someObject afterDelay:0.0] en este momento. De acuerdo con Apple's documentation, esto crea un NSTimer que luego activará y anexará el selector al NSRunLoop actual. Pero no lo considero muy elegante. ¿Hay alguna manera fácil de poner en cola directamente el selector al bucle de ejecución actual sin que Cocoa cree un temporizador, etc.?Encola un selector al ciclo de ejecución - es [NSObject performSelector: withObject: afterDelay:] ¿el camino a seguir?

Would performSelectorOnMainThread:withObject:waitUntilDone: (si estoy en el hilo principal) o performSelector:onThread:withObject:waitUntilDone: con waitUntilDone:NO hago lo que quiero con menos sobrecarga?

Saludos y gracias de antemano

MrMage

Respuesta

6

cacao es por eventos. No "pone en cola un selector dentro del ciclo de ejecución actual". Para decirlo de manera simplista: un evento enviado a la aplicación (entrada de usuario, un temporizador, actividad de red ...) hace que se ejecute el ciclo de ejecución, lo que hace que sucedan cosas en esa ejecución del ciclo. Por supuesto, hay "detalles", pero este es el comportamiento más básico.

Si desea posponer la realización de algún selector al final del ciclo de ejecución actual, llámelo al último, o pida que se ejecute en una ejecución del bucle próxima (muy próxima). Los métodos -performSelector: ... son la forma correcta de hacerlo. Crean un temporizador que resulta en un evento que hace que las cosas sucedan.

Para obtener más información, consulte el Cocoa Event-Handling Guide.

+1

La documentación que he citado dice 'Realiza el selector especificado en el hilo actual durante el siguiente ciclo de ciclo de ejecución y luego de un período de retardo opcional. ' ¿No significa eso que el selector de alguna manera tiene que ser en cola para el siguiente ciclo de ciclo de ejecución? – MrMage

+0

Sí lo hace. :-) Eso es a través de un evento disparado con temporizador. –

+0

He aceptado esta porque me dio la mayor idea de lo que realmente está sucediendo. – MrMage

4

No veo nada poco elegante sobre -performSelector: withObject: afterDelay: método que resalta. Este método simplemente pone en cola una tarea que se realizará después de la finalización del ciclo actual del ciclo de ejecución. Desde el documentation in the section you linked to:

Realiza el selector especificado en el subproceso actual durante el siguiente ciclo de bucle de ejecución y después de un período opcional de retardo . Como espera hasta el siguiente ciclo de ciclo de ejecución para realizar el selector , estos métodos proporcionan un mini retardo automático a partir del código que se está ejecutando actualmente. Múltiples selectores en cola se realizan uno después de otro en el orden en que estaban en cola.

Un objeto NSTimer no se crea para gestionar esto, el selector simplemente se pone en cola para ejecutarse después de un cierto retraso (un pequeño retraso significa inmediatamente después de completar el ciclo de ciclo de ejecución). Para las acciones que desea que sucedan después de las actualizaciones de la interfaz de usuario, esta es la técnica más simple.

Para una cola más explícita y enhebrada, puede consultar NSOperations y NSOperationQueues. Un NSOperationQueue con maxConcurrentOperationCount de 1 puede ejecutar operaciones en orden, una después de la otra.

+0

Crea un temporizador: http://developer.apple.com/mac/library/documentation/cocoa/reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/occ/instm/NSObject/performSelector : withObject: afterDelay: 'Este método configura un temporizador para realizar el mensaje aSelector en el ciclo de ejecución del subproceso actual. El temporizador está configurado para ejecutarse en el modo predeterminado (NSDefaultRunLoopMode). Cuando el temporizador se dispara, el hilo intenta extraer el mensaje del ciclo de ejecución y realizar el selector. – MrMage

+0

Ambos tienen razón. -performSelector: withObject: afterDelay: utiliza la API del temporizador de la base central, no una instancia NSTimer. – NSResponder

+1

Solo quería agregar que la apariencia similar [autoSelector de rendimiento: <#(SEL)#> withObject: <#(id)#>] no espera hasta la próxima ejecución del ciclo de ejecución, sino que llama al método de inmediato. Es obvio, pero aún así lo estoy exponiendo. – SayeedHussain

2

He utilizado esta técnica muchas veces a mí mismo, y no creo que sea tan poco elegante ... sin embargo, una alternativa que podría intentar es:

performSelectorOnMainThread:withObject:waitUntilDone:NO.

El hecho de que ya esté en el hilo principal, no significa que no funcionaría (de hecho, el comportamiento de referencia de los documentos que sucederá cuando se llame desde el hilo principal) ... y creo que tendría el mismo comportamiento cuando waitUntilDone está establecido en NO, donde pone en cola la solicitud para ejecutar el selector y ejecutarlo cuando finaliza el ciclo de ejecución actual.

+0

Escribí sobre eso en mi propia publicación ... – MrMage

+0

Hmm, mis disculpas, supongo que me perdí eso al final. Sin embargo, es una mejor manera de hacer lo que quieres hacer. –

4

Prefiero el método NSRunLoop "performSelector: target: argument: order: modes:". Se garantiza que no ejecutará el selector hasta la próxima iteración del ciclo de ejecución, y no tendrá que perder el tiempo especificando demoras arbitrarias, etc.

Cuestiones relacionadas