检查方法是否存在


110

有什么方法可以测试Objective-C中是否存在方法?

我试图添加一种保护措施,以在调用它之前查看我的对象是否具有该方法。


还有一个问题是,这首先是否是正确的方法,因为Objective-C类可以响应未声明的选择器(通过- forwardInvocation:)。
Donal Fellows 2010年

Answers:


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

72

还有静态消息instanceRespondToSelector:(SEL)selector 您可以这样称呼它:

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

或像这样:

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

如果您要根据此调用一个构造函数或另一个构造函数(这是在拥有实例本身之前),则这可能很有用。


1
instancesRespondToSelector和responsToSelector有什么不同?
CReaTuS 2012年

1
主要区别在于,一个是实例消息(用于测试确定的实例消息是否确实存在),而另一个是类消息(用于测试确定的类消息是否确实存在)。
RicardPérezdel Campo

1
+1对于[MyClass instanceRespondToSelector]。我需要在一个init创建方法中使用它:当可能需要子类调用一个超级init方法而不是其他方法(不推荐使用)时,因为还没有创建self,responsToSelector将始终返回NO。
LightMan

12

使用respondsToSelector:。从文档中

responsesToSelector:

返回一个布尔值,该值指示接收方是否实现或继承可以响应指定消息的方法。

- (BOOL)respondsToSelector:(SEL)aSelector

参数
aSelector-标识消息的选择器。


YES如果接收者实现或继承了可以响应aSelector的方法,则返回Value,否则返回NO


10

您在寻找responsToSelector: -

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

正如Donal所说的,上面告诉您foo 绝对可以处理接收bar选择器。但是,如果foo是将bar转发到某些将接收到bar消息的基础对象的代理,则即使消息将转发到响应bar的对象,responsToSelector:也会告诉您NO。


1

通常,仅使用委托方法通过responsToSelector检查选择器。您不应该对委托方法使用forwardInvocation或proxy。如果在其他情况下需要使用responsToSelector,则可能需要确保没有更合适的方法来设计程序。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.