Compruebe si existe un método

110

¿Hay alguna forma de que pueda probar si existe un método en Objective-C?

Estoy tratando de agregar un guardia para ver si mi objeto tiene el método antes de llamarlo.

teepusink
fuente
También está la cuestión de si este es el enfoque correcto en primer lugar, ya que las clases Objective-C pueden responder a selectores que no han declarado (vía - forwardInvocation:).
Donal Fellows

Respuestas:

189
if ([obj respondsToSelector:@selector(methodName:withEtc:)]) {
   [obj methodName:123 withEtc:456];
}
Kennytm
fuente
72

También está el mensaje estático instanceRespondToSelector: (SEL) selector Lo llamaría así:

[MyClass instancesRespondToSelector:@selector(someMethod:withParams:)]

o así:

[[myObject class] instancesRespondToSelector:@selector(someMethod:withParams:)]

Esto puede ser útil si desea llamar a un constructor u otro dependiendo de esto (quiero decir, antes de tener la instancia en sí).

Ricard Pérez del Campo
fuente
1
¿Qué diferencia hay de instanceRespondToSelector de respondsToSelector?
CReaTuS
1
La principal diferencia es que uno es un mensaje de instancia (para probar si existe un mensaje de instancia determinado) mientras que el otro es un mensaje de clase (para probar si existe un mensaje de clase determinado).
Ricard Pérez del Campo
1
+1 para [MyClass instanceRespondToSelector]. Lo necesitaba dentro de un método de creación de inicio: cuando se subclasifica, tal vez sea necesario llamar a un método de superinicialización en lugar de otros (en desuso), ya que self aún no se ha creado y respondsToSelector siempre devolverá NO.
LightMan
12

Utilice respondsToSelector:. De la documentación :

respondeToSelector:

Devuelve un valor booleano que indica si el receptor implementa o hereda un método que puede responder a un mensaje específico.

- (BOOL)respondsToSelector:(SEL)aSelector

Parámetros
aSelector : un selector que identifica un mensaje.

Valor de retorno
YES si el receptor implementa o hereda un método que puede responder a aSelector , en caso contrario NO.

Carl Norum
fuente
10

Estás buscando respondsToSelector: -

if ([foo respondsToSelector: @selector(bar)] {
  [foo bar];
}

Como dice Donal, lo anterior te dice que foo definitivamente puede manejar la recepción del selector de barras. Sin embargo, si foo es un proxy que reenvía la barra a algún objeto subyacente que recibirá el mensaje de barra, entonces respondeToSelector: le dirá NO, aunque el mensaje se reenviará a un objeto que responde a la barra.

Frank Shearar
fuente
1

La verificación de selectores con respondsToSelector es normalmente solo para métodos delegados. No debería utilizar forwardInvocation o proxies para los métodos delegados. Si necesita utilizar respondsToSelector en otras situaciones, es posible que desee asegurarse de que no haya una forma más adecuada de diseñar su programa.

Eric
fuente