如果实例responsedsToSelector - 为什么仍然“无法识别的选择器发送到实例”?

时间:2014-03-02 07:22:44

标签: objective-c macos objective-c-runtime respondstoselector

是的,我正式感到困惑。

这在10.8的NSTableView子类中调用,我们可以从the docs学习,标题NSTableView实现NSDraggingSource所以一切都应该是好的:

 if ([super respondsToSelector:@selector(draggingSession:movedToPoint:)])
    [super draggingSession:session movedToPoint:screenPoint];

当调用包含方法(子类中的draggingSession:movedToPoint:的覆盖)时,第二行会抛出心爱的'无法识别的选择器发送到实例0x1054092c0 '异常。

是否有人解释这里发生了什么?!

3 个答案:

答案 0 :(得分:3)

首先,[super respondsToSelector:@selector(draggingSession:movedToPoint:)][self respondsToSelector:@selector(draggingSession:movedToPoint:)]相同。 super允许您调用给定方法的超类实现;在这种情况下,respondsToSelector:。但是如果你的类(或者这个对象是什么类)没有覆盖-respondsToSelector:(99.9%的类不需要覆盖-respondsToSelector:),那么超类的实现与类的实现相同self。基本上,在这两种情况下,您都要检查当前对象(self)是否响应选择器。

所以,你所看到的是:self响应选择器,但是这个类的超类没有选择器的实现。那是什么意思?无论是当前类,还是当前类之间的某个类self,都实现了此方法。这就是self回应它的原因。但是没有超类实现。

答案 1 :(得分:0)

正确的代码实际上是:

if ([[NSTableView class] instancesRespondToSelector:@selector(draggingSession:movedToPoint:)])
    [super draggingSession:session movedToPoint:screenPoint];

正如newacct所指出的那样,super指的是实现该方法的类的超类,而[self superclass]是调用它的实例的超类,它可以是自定义类的子类(NSTableView的孙子)。当然,你不太可能创建这样一个子子类,但你也可以做正确的事情,而且这个代码无论如何都更清晰。

答案 2 :(得分:-1)

感谢提示 -
这确实很好用:

 if ([[self superclass] instancesRespondToSelector:@selector(draggingSession:movedToPoint:)])
    [super draggingSession:session movedToPoint:screenPoint];