2010-09-12 9 views
57
- (void)someMethod 
{ 
    if ([delegate respondsToSelector:@selector(operationShouldProceed)]) 
    { 
     if ([delegate operationShouldProceed]) 
     { 
      // do something appropriate 
     } 
    } 
} 

El documentation dice:cuándo utilizar respondsToSelector en Objective-C

La precaución es necesaria sólo para los métodos opcionales en un protocolo formal o métodos de un protocolo estructurado

Lo que hace ¿significa? Si utilizo un protocolo formal, ¿puedo usar [delegate myMethod]?

Respuesta

74

Lo usa prácticamente cuando lo necesita: para verificar si un objeto implementa el método que está a punto de llamar. Generalmente esto se hace cuando tiene un método opcional o un protocolo informal.

Solo he usado respondsToSelector cuando estoy escribiendo código que debe comunicarse con un objeto delegado.

if ([self.delegate respondsToSelector:@selector(engineDidStartRunning:)]) { 
     [self.delegate engineDidStartRunning:self]; 
    } 

A veces se desea utilizar respondsToSelector en cualquier método que devuelve y id o genérico NSObject donde no está seguro de lo que la clase del objeto devuelto es.

+0

gracias. Entiendo ahora.Noté que usas self.delegate, que es una propiedad. Solo uso una variable de instancia: delegado id. ¿cual es la diferencia? Estoy aprendiendo objetivo-c. gracias de nuevo – Taho

+2

'self.delegate' es exactamente lo mismo que llamar' [self delegate] '. En mi código no hay diferencia entre '[self.delegate someMethod]' y '[_delegate someMethod]', pero tiendo a usar sintaxis de punto porque mantiene en mi mente las variables que son locales para el método en el que estoy y que son variables de instancia. – kubi

+0

Si recién está comenzando, valdrá la pena leer la guía de Apple para Obj-C. http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocProperties.html%23//apple_ref/doc/uid/TP30001163-CH17 – kubi

45

Solo para agregar a lo que dice @kubi, en otra ocasión lo uso cuando se agrega un método a una clase preexistente en una versión más nueva de los marcos, pero todavía necesito compatibilidad con versiones anteriores. Por ejemplo:

if ([myObject respondsToSelector:@selector(doAwesomeNewThing)]) { 
    [myObject doAwesomeNewThing]; 
} else { 
    [self doOldWorkaroundHackWithObject:myObject]; 
} 
2

vieja pregunta, pero he aprendido a ser muy cautios con el uso de cosas como addTarget: @selector (fu :) porque el nombre del método no está marcada ni incluido en la refactorización por XCODE. Esto ya me ha causado bastante problemas. Así que ahora he hecho un habito de siempre incrustar o cosas por el estilo addTarget addObserver en un respondsToSelector-Check de este modo:

if([self respondsToSelector:@selector(buttonClicked:)]){ 
    [self.button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside]; 
}else{ 
    DebugLog(@"Warning - a class or delegate did not respond to selector in class %@", self); 
} 

Sé que no es muy elegante, pero yo prefiero añadir algo de código reutilizable que tiene un inesperado falla de mis aplicaciones en la App Store.

+0

Creo que "methodName:" ahora está marcado en sentencias como @selector (methodName :) en xCode, ¿no es así? – Grezzo

+1

@Grezzo - XCode solo comprobará que el selector exista en algún lugar de su destino. Entonces, por ejemplo, si escribió '@selector (date)' en lugar de '@selector (data)' XCode no lo advertirá porque el selector 'date' existe en' NSDateComponents'. – Robert

11

Como kubi mencionó respondsToSelector se usa normalmente cuando tiene una instancia de un método que se ajusta a un protocolo.

// Extend from the NSObject protocol so it is safe to call `respondsToSelector` 
@protocol MyProtocol <NSObject> 

// @required by default 
- (void) requiredMethod; 

@optional 

- (void)optionalMethod; 

@end 

Dado e instancia de este protocolo podemos llamar de forma segura a cualquier método requerido.

id <MyProtocol> myObject = ... 
[myObject requiredMethod]; 

Sin embargo, los métodos opcionales pueden o no implementarse, por lo que debe verificar en tiempo de ejecución.

if ([myObject respondsToSelector:@selector(optionalMethod)]) 
{ 
    [myObject optionalMethod]; 
} 

Esto evitará un bloqueo con un selector no reconocido.


Además, la razón por la que debe declarar protocolos como una extensión de NSObjects, es decir

@protocol MyProtocol <NSObject> 

se debe a que el protocolo NSObject declara el selector respondsToSelector:. De lo contrario, XCode pensaría que no es seguro llamarlo.

+0

Me olvidé de agregar resuelto mi problema gracias –