Verifique se existe um método

111

Existe alguma maneira de testar se existe um método em Objective-C?

Estou tentando adicionar um guarda para ver se meu objeto tem o método antes de chamá-lo.

teepusink
fonte
Há também a questão de saber se esta é a abordagem certa em primeiro lugar, uma vez que classes Objective-C podem responder a seletores que não declararam (via - forwardInvocation:).
Donal Fellows

Respostas:

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

Há também a mensagem estática instancesRespondToSelector: (SEL) selector Você o chamaria assim:

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

ou assim:

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

Isso pode ser útil se você quiser chamar um construtor ou outro dependendo disso (quero dizer, antes de ter a própria instância).

Ricard Pérez del Campo
fonte
1
Qual é a diferença entre instancesRespondToSelector e respondsToSelector?
CReaTuS
1
A principal diferença é que uma é uma mensagem de instância (para testar se uma mensagem de determinada instância existe) enquanto a outra é uma mensagem de classe (para testar se uma mensagem de classe determinada existe).
Ricard Pérez del Campo,
1
+1 Para [MyClass instancesRespondToSelector]. Eu precisava disso dentro de um método de criação de init: Ao criar uma subclasse, talvez seja necessário chamar um método super init em vez de outros (os obsoletos), já que self ainda não foi criado e respondsToSelector sempre retornará NO.
LightMan
12

Use respondsToSelector:. Da documentação :

respondsToSelector:

Retorna um valor booleano que indica se o receptor implementa ou herda um método que pode responder a uma mensagem especificada.

- (BOOL)respondsToSelector:(SEL)aSelector

Parâmetros
aSelector - Um seletor que identifica uma mensagem.

Valor de retorno
YES se o receptor implementa ou herda um método que pode responder a umSeletor , caso contrário NO.

Carl Norum
fonte
10

Você está procurando por respondsToSelector: -

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

Como Donal disse, o acima indica que foo definitivamente pode receber o seletor de barra. No entanto, se foo for um proxy que encaminha bar para algum objeto subjacente que receberá a mensagem bar, então respondsToSelector: dirá NÃO, mesmo que a mensagem seja encaminhada para um objeto que responde bar.

Frank Shearar
fonte
1

Verificar seletores com respondsToSelector normalmente é apenas para métodos delegados. Você não deve usar forwardInvocation ou proxies para métodos delegados. Se você precisar usar respondsToSelector em outras situações, certifique-se de que não haja uma maneira mais apropriada de projetar seu programa.

Eric
fonte