与-respondsToSelector等效的类方法:


68

是否有一个等效于的类方法-respondsToSelector:

+respondsToSelector:什么?

我问的原因是因为通过-respondsToSelector:在类级别上实现,我得到了编译器警告:“在协议中找到了'-respondsToSelector:'而不是'+ respondsToSelector:'”。

代码如下:

Class <SomeProtocol> someClass = [someInstance class];

if ([someClass respondsToSelector:@selector(someSelector:)]) {
    someVar = [someClass someSelector:someData];
}

Answers:


83

看到您的修改后进行更新:

respondsToSelector:您可能已经知道,类对象的响应很好。在测试应用程序中,我可以在没有任何编译器警告的情况下执行以下两项操作:

NSLog(@"Responds to selector? %i", [MyObject respondsToSelector:@selector(respondsToSelector:)]);
NSLog(@"Responds to selector? %i", [[MyObject class] respondsToSelector:@selector(respondsToSelector:)]);

但是,您已经在变量上声明了一个协议,因此它假定您要指向的类对象实现了这些方法。最简单的解决办法是投someClass作为一个id用于通话的目的respondsToSelector:。一种更简洁的解决方案是声明自己的@protocol声明+respondsToSelector:(SEL)selector,然后声明someClass如下:

Class<SomeProtocol, ClassRespondingToSelector> someClass = ...

最后,请确保通过http://bugreporter.apple.com向Apple提交错误。包括一个简单的测试应用程序,以使您很清楚自己在做什么。他们欢迎此类错误报告,即使它们是过去提交的,也可以帮助他们确定修复的优先级。

最后一点:这可能是发生的,因为从理论上讲,您可以选择实现与NSObject完全分开的根对象,在这种情况下,它不会响应-respondsToSelector:-[NSObject respondsToSelector:]实际上是在NSObject协议中声明,而不是在类定义中声明。该NSObject协议实际上是您所知道的大多数NSObject实际生活的地方。有人可能会争辩+respondsToSelector:说它也应该在那里,但是到目前为止,还没有。而且,由于您已经提供了协议列表,并且该方法不在其中,因此它会向您发出警告,以确保您知道自己在做什么。


我相信在这种情况下,他实际上想转换为Class,而不是id。
Joseph Lennox

7
这是删除的功能,还是答案不清楚。Class没有回应respondsToSelector:
RileyE 2014年

试试看。它不在标题中,但在标题中id classObject = [SomeClass class]; [classObject respondsToSelector:]
BJ Homer 2014年

1
正如BJ Homer所说,它实际上有效,它不在标题中,因此无法通过Xcode自动完成。这就是让我感到怀疑的原因。您需要完全键入它。
wolfrevo

@RileyE同意,我也遇到了这个问题,respondToSelector在中找不到等效项Class
Ratul Sharker

9

好吧,类方法只是类对象的方法,因此您应该能够做到这一点

[MyClass respondsToSelector:@selector(...)]

我收到一个编译器警告:“在协议中找到“ -respondsToSelector:”而不是“ + respondsToSelector:””。如何摆脱该编译器警告?
firstresponder

我可以通过删除协议类型限定符“ <SomeProtocol>”来摆脱编译器警告。这是为什么?该语法不正确吗?
firstresponder

3
firstresponder:Objective-C是一种动态语言。如果将消息发送给Classid不进一步(使用协议)来限定该类型,则编译器会假设您正在对自己的选择响应或同类进行检查。但是,如果您确实指定了协议或(例如)特定类,它会有所帮助并为您执行检查。由于您使用声明变量的协议没有+respondsToSelector:声明,因此编译器会发出警告。
Peter Hosey

我注意到Xcode 9中协议行为的转换是不同的。它在此处接受转换,但在8及更低版本中不接受。
Will Larche

5

instancesRespondToSelector:从iOS 2.0开始,您可以使用以下内容,因此可以在类的实例中进行操作;

[myInstance respondsToSelector: @selector(...)];

上课时,您可以使用

[myClass instanceRespondsToSelector: @selector(...)];
// or
[[myInstance class] instanceRespondsToSelector: @selector(...)];

会表现得像 +(BOOL) respondsToSelector


6
如果类的实例将对选择器做出响应,这将做出回答,而如果类本身将静态地对选择器做出响应,则将做出回答。
Jonny

2

我想您要问的是:您可以问一堂课是否回应+someMethod吗?换句话说,考虑到Cocoa Touch API,您需要:

[ [ UIView class ] respondsToSelector: @selector( buttonWithType: ) ] -> NO
[ [ UIButton class ] respondsToSelector: @selector( buttonWithType: ) ] -> YES

但是我在上面写的内容并不能按需工作。respondsToSelector:仅关于实例方法。(因此,这两个调用都将返回NO。)在Cocoa API中,没有等效于respondsToSelector:类的类。

但是,您可以致电class_getClassMethod。如果结果为非NULL,存在您要询问的类方法,您可以调用它。


8
这是错误的。respondsToSelector:Class对象上正常工作以报告类方法的存在。
Dave DeLong 2010年

我赞成这个家伙,因为他实际上是正确的class_getClassMethod。如果我有足够的耐心来阅读整个线程,则不必重新发明相同的解决方案。
bioffe

1
我对此表示反对,因为类方法类对象上的实例方法。
2011年

4
-1您正在描述的行为+instancesRespondToSelector:-respondsToSelector:类对象上的工作原理完全不同。

0

在Objective C中,类也是对象,因此您可以发送对象消息。特别是,您可以要求-respondsToSelector:上一堂课。但是,您不能将类级别的方法发送给非类对象。

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.