Para este ejemplo muy básico en la pregunta,
[object doSomething];
[object performSelector:@selector(doSomething)];
no hay ninguna diferencia en lo que va a ocurrir. 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.
eran algo un poco más complicado, como:
(void)doSomethingWithMyAge:(NSUInteger)age;
las cosas se complican, porque [objeto 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í habría "doSomethingWithMyAge:" pero cualquier intento de
[object performSelector:@selector(doSomethingWithMyAge:) withObject:42];
simplemente no se compilará. pasar un NSNumber: @ (42) en lugar de 42, tampoco ayudaría, porque el método espera un tipo de C básico, no un objeto.
Además, hay variantes de performSelector de hasta 2 parámetros, no más. Mientras que los métodos muchas veces tienen muchos más parámetros.
He descubierto que aunque las variantes sincrónicas de performSelector:
- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
siempre devuelven un objeto, yo era capaz de devolver un BOOL simple o NSUInteger también, y ha funcionado.
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
SEL method = NSSelectorFromString([NSString stringWithFormat:@"doSomethingWithMy%@:", @"Age");
[object performSelector:method];
El otro uso, es enviar un mensaje de forma asíncrona a oponerse, que será ejecutado más tarde en el runloop actual. Para esto, hay varias otras variantes de performSelector.
- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray *)modes;
- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay;
- (void)performSelector:(SEL)aSelector target:(id)target argument:(id)arg order:(NSUInteger)order modes:(NSArray *)modes;
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array;
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array;
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;
- (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg;
(sí juntélos de varias categorías de clase de la Fundación, como NSThread, NSRunLoop y NSObject)
Cada una de las variantes tiene su propio comportamiento especial, pero todos comparten algo en común (al menos cuando waitUntilDone está configurado a NO). La llamada "performSelector" volverá inmediatamente, y el mensaje a objeto solo se pondrá en el runloop actual después de un tiempo.
Debido a la ejecución retrasada, naturalmente no hay valor de retorno disponible del método del selector, de ahí el valor de retorno (vacío) en todas estas variantes asincrónicas.
espero que cubrí esto de alguna manera ...
Vale la pena señalar que en realidad le asigne el resultado de findTheAppropriateSelectorForTheCurrentSituation() para aSelector y luego invoque [unObjeto performSelector: aSelector]. @selector produce un SEL. –
El uso de 'performSelector:' es algo que probablemente solo haga si implementa action-target en su clase. Los hermanos 'performSelectorInBackground: withObject:' y 'performSelectorOnMainThread: withObject: waitUntilDone:' a menudo son más útiles. Para generar un hilo de fondo y para devolver los resultados al hilo principal de dicho hilo de fondo. – PeyloW
'performSelector' también es útil para suprimir las advertencias de compilación. Si sabe que el método existe (como después de usar 'respondsToSelector'), detendrá que Xcode diga" puede que no responda a 'your_selector'". Simplemente no lo use _en lugar_ de averiguar la causa real de la advertencia.;) – Marc