De lo que he aprendido hasta el momento: En Objective-C, que usted puede enviar cualquier mensaje a cualquier objeto. Si el objeto de no aplicar el método correcto será ejecutado de lo contrario no pasará nada. Esto es debido a que antes de enviar el mensaje Objective-C llevará a cabo respondsToSelector.

Espero estoy en lo cierto hasta el momento.

Hice un pequeño programa para probar que una acción es invocado cada vez que un deslizador se mueve. También para las pruebas he fijado que el remitente NSButton pero en realidad es un NSSlider. Ahora he pedido el objeto si se va a responder a setAlternateTitle. Mientras que un NSButton va a hacer y NSSlider no. Si puedo ejecutar el código y hacer respondsToSelector a mí me va a decir que el objeto no responde a ese selector. Si puedo probar alguna otra cosa, como intValue, va a responder. Así que mi código está bien hasta el momento.

- (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 voy a enviar el setAlternateTitle mensaje de que el programa se bloqueará y no estoy exactamente seguro de por qué. No debería hacer un respondsToSelector antes de enviar el mensaje?

InformationsquelleAutor TalkingCode | 2011-01-01

4 Comentarios

  1. 152

    Primero de todos, el nombre de un método (el selector) incluye todas las subpartes de colon y de caracteres, como mvds dijo.

    En segundo lugar, el método -respondsToSelector: no es llamado por el tiempo de ejecución, se le suele llamar por el usuario (usted o Api que quieren saber si un delegado, por ejemplo, responde a un método opcional para el protocolo).

    Cuando usted 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 objeto de isa puntero). Es equivalente a enviar -respondsToSelector: aunque el mensaje no es enviado. Si la aplicación del método se encuentran en la clase o en sus superclases, se llama con todos los argumentos que se le pasan.

    Si no, entonces el tiempo de ejecución da el mensaje de una segunda oportunidad para ser ejecutado. Se empezará a enviar el mensaje + (BOOL)resolveInstanceMethod:(SEL)name a la clase del objeto: este método permite que usted agregue el método en tiempo de ejecución para la clase: si este mensaje devuelve SÍ, significa que se puede redispatch el mensaje.

    Si no se da el mensaje de una tercera oportunidad para ser ejecutado, envía - (id)forwardingTargetForSelector:(SEL)aSelector con el selector, este método puede devolver otro objeto que pueda ser capaz de responder a las selector en nombre de la real receptor, si el objeto devuelto puede responder, se ejecuta el método y el valor es devuelto 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 nula o auto (para evitar bucles infinitos), el tiempo de ejecución da el mensaje de una cuarta oportunidad para ejecutar el método… Se envía el mensaje - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector para obtener una firma de método con el fin de construir una invocación. Si se proporciona a continuación una invocación se envía a través del mensaje de - (void)forwardInvocation:(NSInvocation *)anInvocation. En este método se puede analizar la invocación y construir otros mensajes para enviar a otros objetivos en cualquier forma que desee y, a continuación, puede establecer el valor de retorno de la invocación… Que valor va a actuar como el valor de retorno del mensaje original.

    Finalmente, si no hay ningún método de firma es devuelto por el objeto, entonces el tiempo de ejecución se envía el mensaje - (void)doesNotRecognizeSelector:(SEL)aSelector a su objeto, la aplicación de este método en la clase NSObject lanza una excepción.

    • +1 por esta excelente explicación. ¿Puede dar algunos link donde esta todo el proceso está documentado en detalle. Vale la pena leer.
    • La documentación está aquí: developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/… en la parte… Otras cosas son en referencia de la clase NSObject
    • por el camino, forwardingTargetForSelector: es sólo en Mac OS X 10.6+ o iOS 4+
    • «Puede invalidar este método para silenciosamente fallar en el manejo de los mensajes.» Apple docs dice específicamente que este método siempre debe dar una excepción, de manera que fallar en silencio viola el contrato: developer.apple.com/library/mac/#documentation/Cocoa/Reference/…:
    • La excepción se bloquea la app en iOS, pero no en Mac OS X, ¿verdad?
    • Esa es una muy buena e importante de la nota, gracias por compartir. Te mereces más upvotes para ello. He editado la respuesta a incluir esa nota.
    • * * * * B R A V O ! * *

  2. 7

    Para una cosa, el selector no es sólo el «nombre» del mensaje, pero también lo que sigue, es decir, los argumentos, y sus nombres.

    Para la correcta selección de algunos -(void)setAlternateTitle:(NSString*)str sería

    @selector(setAlternateTitle:)

    con la :

    Como para su problema: Si una clase respondsToSelector() y realizar ese selector, usted no debería tener una falla en el envío de un desconocido selector. ¿Qué tipo de registro de bloqueo se ven en la ventana de depuración?

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

    • Con más precisión, un selector de no incluir «lo que sigue, es decir, los argumentos, y sus nombres», pero «el número y la posición de los argumentos en el nombre del mensaje».
  3. 2

    «Esto es debido a que antes de que el mensaje es
    enviado Objective-C va a realizar
    respondsToSelector.»

    Supongo que esto no es correcto. Si el objeto no responde a la selección, se estrellará en tiempo de ejecución. No hay ninguna comprobación automática por el sistema. Si no fue un cheque por el tiempo de ejecución del sistema, a continuación, nunca debemos conseguir «desconocido selector enviado a la instancia de excepción.

    Por favor, hacer que me corrija si estoy equivocado.

    EDIT: Esto no es una línea recta hacia adelante accidente, pero el resultado predeterminado es el proceso de ser terminado. Toda la secuencia está ya explicado en el comentario y otra respuesta, así que no voy a escribir de nuevo.

    • No se cae, se cae de nuevo a un proceso llamado reenvío de. Por desgracia, esto no parece estar bien documentada, pero hace varias cosas: primero que llama +resolveInstanceMethod: en el receptor de la clase. Si esto falla, llama a -forwardingTargetForSelector:, entonces -forwardInvocation:. La implementación predeterminada de -forwardInvocation: lanza un sin aplicarse selector de excepción, que no es lo mismo un accidente.
    • gracias por la explicación. Yo no conocía esta secuencia. En realidad no es una recta hacia adelante accidente, como un fallo de segmentación, pero el resultado predeterminado parece que el proceso se dará por terminado.
    • Al menos yo tenía la razón de que el método no es llamado automáticamente por el sistema.
  4. 2

    Hay un +instancesRespondToSelector: método. Como el nombre sugiere, se dice que si las instancias de la clase implementar ese método.

Dejar respuesta

Please enter your comment!
Please enter your name here