versiones programación objective lenguaje framework español ejemplos objective-c cocoa

objective c - programación - Objective-C respondesSelector



versiones de objective c (4)

"Esto se debe a que antes de que se envíe el mensaje, Objective-C ejecutará respondsToSelector".

Supongo que esto no es correcto. Si el objeto no responde al selector, se bloqueará en el tiempo de ejecución. No hay comprobación automática por el sistema. Si hubo una verificación por parte del sistema de tiempo de ejecución, nunca deberíamos obtener la excepción de "selector no enviado a la instancia".

Por favor, hazme correcto si estoy equivocado.

EDITAR: Esto no es una falla directa, pero el resultado predeterminado es que el proceso terminará. La secuencia completa ya está explicada en el comentario y en otra respuesta, así que no voy a escribir eso otra vez.

De lo que he aprendido hasta ahora: En Objective-C puedes enviar cualquier mensaje a cualquier objeto. Si el objeto implementa el método correcto, se ejecutará de lo contrario no pasará nada. Esto se debe a que, antes de enviar el mensaje, Objective-C realizará respondsToSelector .

Espero tener razón hasta ahora.

Hice un pequeño programa para probar dónde se invoca una acción cada vez que se mueve un control deslizante. También para las pruebas, configuro el remitente en NSButton, pero en realidad es un NSSlider. Ahora le pregunté al objeto si responderá a setAlternateTitle . Mientras que un NSButton hará y NSSlider no. Si ejecuto el código y responsToSelector yo mismo, me dirá que el objeto no responderá a ese selector. Si pruebo algo más como intValue , responderá. Así que mi código está bien hasta ahora.

- (IBAction)sliderDidMove:(id)sender { NSButton *slider = sender; BOOL responds = [slider respondsToSelector:@selector(setAlternateTitle)]; if(responds == YES) { NSLog(@"YES"); } else { NSLog(@"NO"); } [slider setAlternateTitle:@"Hello World"]; }

Pero cuando en realidad envío el mensaje setAlternateTitle, el programa se bloqueará y no estoy exactamente seguro de por qué. ¿No debería hacer un respondsToSelector antes de enviar el mensaje?


En primer lugar, el nombre de un método (su selector) incluye todas las subpartes y los dos puntos, como dice mvds.

En segundo lugar, el método -respondsToSelector: no es llamado por el tiempo de ejecución, generalmente lo llama el usuario (usted mismo o las API que desean saber si un delegado, por ejemplo, responde a un método opcional del protocolo).

Cuando envía un mensaje a un objeto, el tiempo de ejecución buscará la implementación del método en la clase del objeto (a través del puntero isa del objeto). Es equivalente a enviar -respondsToSelector: aunque el mensaje en sí no se envía. Si la implementación del método se encuentra en la clase o en sus superclases, se llama con todos los argumentos que se pasaron.

Si no, el tiempo de ejecución le da al mensaje una segunda oportunidad para ejecutarse. Comenzará enviando el mensaje + (BOOL)resolveInstanceMethod:(SEL)name a la clase del objeto: este método le permite agregar el método en tiempo de ejecución a la clase: si este mensaje devuelve SÍ, significa que puede volver a rastrear mensaje.

Si no le da al mensaje una tercera oportunidad de ser ejecutado, envía - (id)forwardingTargetForSelector:(SEL)aSelector con el selector, este método puede devolver otro objeto que pueda responder al selector en nombre del receptor real , si el objeto devuelto puede responder, el método se ejecuta y el valor se devuelve como si fuera devuelto por el mensaje original. (Nota: esto está disponible a partir de OS X 10.6 o iOS 4.)

Si el objeto devuelto es nil o self (para evitar bucles infinitos), el tiempo de ejecución le da al mensaje una cuarta oportunidad de ejecutar el método ... Envía el mensaje - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector para obtener una firma de método en orden para construir una invocación. Si se proporciona uno, se envía una invocación a través del mensaje - (void)forwardInvocation:(NSInvocation *)anInvocation . En este método, puede analizar la invocación y generar otros mensajes para enviarlos a otros destinos de la forma que desee, y luego puede establecer el valor de retorno de la invocación ... Ese valor actuará como el valor de retorno del mensaje original.

Finalmente, si el objeto no devuelve ninguna firma de método, entonces el tiempo de ejecución envía el mensaje - (void)doesNotRecognizeSelector:(SEL)aSelector a su objeto, la implementación de este método en la clase NSObject lanza una excepción.


Hay un método +instancesRespondToSelector: . Como su nombre lo indica, le indica si las instancias de la clase implementan ese método.


Por un lado, el selector no es solo el "nombre" del mensaje, sino también lo que sigue, es decir, los argumentos y sus nombres.

Así que el selector correcto para algunos -(void)setAlternateTitle:(NSString*)str sería

@selector(setAlternateTitle:)

con el

En cuanto a su problema: si una clase respondsToSelector() y usted realiza ese selector, no debería bloquearse al enviar un selector desconocido. ¿Qué tipo de registro de fallos ve en la ventana de depuración?

(ps. ¿por qué no incluir el [slider setAlternateTitle:...] en el bloque condicional if ( responds ) { ... } ?)