Todavía soy algo nuevo en Objective-C y me pregunto cuál es la diferencia entre las siguientes dos declaraciones.
[object performSelector:@selector(doSomething)];
[object doSomething];
objective-c
selector
dynamic-languages
method-dispatch
El jugador
fuente
fuente
performSelector:
es algo que probablemente solo haga si implementa target-action en su clase. Los hermanosperformSelectorInBackground:withObject:
yaperformSelectorOnMainThread:withObject:waitUntilDone:
menudo son más útiles. Para generar un hilo en segundo plano y para devolver los resultados al hilo principal desde dicho hilo en segundo plano.performSelector
también es útil para suprimir las advertencias de compilación. Si sabe que el método existe (como después de usarlorespondsToSelector
), evitará que Xcode diga "puede que no respondayour_selector
". Simplemente no lo use en lugar de averiguar la causa real de la advertencia. ;)Para este ejemplo muy básico en la pregunta,
no hay diferencia en lo que va a pasar. doSomething se ejecutará sincrónicamente por objeto. Solo "doSomething" es un método muy simple, que no devuelve nada y no requiere ningún parámetro.
si fuera algo un poco más complicado, como:
las cosas se complicarían, porque [object doSomethingWithMyAge: 42];
ya no se puede llamar con ninguna variante de "performSelector", porque todas las variantes con parámetros solo aceptan parámetros de objeto.
El selector aquí sería "doSomethingWithMyAge:" pero cualquier intento de
simplemente no se compilará. pasar un NSNumber: @ (42) en lugar de 42, tampoco ayudaría, porque el método espera un tipo C básico, no un objeto.
Además, existen variantes de performSelector de hasta 2 parámetros, no más. Mientras que los métodos muchas veces tienen muchos más parámetros.
Descubrí que aunque las variantes sincrónicas de performSelector:
Siempre devuelve un objeto, también pude devolver un BOOL simple o NSUInteger, y funcionó.
Uno de los dos usos principales de performSelector es componer dinámicamente el nombre del método que desea ejecutar, como se explicó en una respuesta anterior. Por ejemplo
El otro uso es enviar de forma asincrónica un mensaje al objeto, que se ejecutará más tarde en el runloop actual. Para ello, existen otras variantes de performSelector.
(sí, los reuní de varias categorías de clases de la Fundación, como NSThread, NSRunLoop y NSObject)
Cada una de las variantes tiene su propio comportamiento especial, pero todas comparten algo en común (al menos cuando waitUntilDone se establece en NO). La llamada "performSelector" volverá inmediatamente y el mensaje al objeto solo se pondrá en el runloop actual después de un tiempo.
Debido a la ejecución retrasada, naturalmente, no hay ningún valor de retorno disponible desde el método del selector, de ahí el valor de retorno - (vacío) en todas estas variantes asincrónicas.
Espero haber cubierto esto de alguna manera ...
fuente
@ennuikiller da en el clavo. Básicamente, los selectores generados dinámicamente son útiles para cuando no (y normalmente no es posible) sabe el nombre del método al que llamará cuando compile el código.
Una diferencia clave es que
-performSelector:
y los amigos (incluidas las variantes de subprocesos múltiples y retardados ) son algo limitados en el sentido de que están diseñados para su uso con métodos con parámetros 0-2. Por ejemplo, llamar-outlineView:toolTipForCell:rect:tableColumn:item:mouseLocation:
con 6 parámetros y devolver elNSString
es bastante difícil de manejar y no es compatible con los métodos proporcionados.fuente
NSInvocation
objeto.performSelector:
todos los amigos toman argumentos de objeto, lo que significa que no puede usarlos para llamar (por ejemplo)setAlphaValue:
, porque su argumento es un flotante.Los selectores son un poco como punteros de función en otros idiomas. Los usa cuando no sabe en tiempo de compilación a qué método desea llamar en tiempo de ejecución. Además, al igual que los punteros de función, solo encapsulan la parte verbal de la invocación. Si el método tiene parámetros, deberá pasarlos también.
An
NSInvocation
tiene un propósito similar, excepto que une más información. No solo incluye la parte del verbo, también incluye el objeto de destino y los parámetros. Esto es útil cuando desea llamar a un método en un objeto particular con parámetros particulares, no ahora sino en el futuro. Puede construir un apropiadoNSInvocation
y dispararlo más tarde.fuente
Hay otra sutil diferencia entre los dos.
Aquí está el extracto de la documentación de Apple
"performSelector: withObject: afterDelay: realiza el selector especificado en el subproceso actual durante el siguiente ciclo de bucle de ejecución y después de un período de retraso opcional. Debido a que espera hasta el siguiente ciclo de bucle de ejecución para realizar el selector, estos métodos proporcionan un mini retraso automático desde el código que se está ejecutando actualmente. Se realizan varios selectores en cola uno tras otro en el orden en que se pusieron en cola ".
fuente
performSelector:withObject:afterDelay:
, pero la pregunta y su fragmento están usandoperformSelector:
, que es un método completamente diferente. De los documentos para ello: <quote> ElperformSelector:
método es equivalente a enviar unaSelector
mensaje directamente al receptor. </quote>performSelector/performSelector:withObject/performSelector:withObject:afterDelay
todos se comportaban de la misma manera, lo cual fue un error.