从子类中移除一个动作

Posted

技术标签:

【中文标题】从子类中移除一个动作【英文标题】:Removing an action from a subclass 【发布时间】:2013-10-04 21:34:05 【问题描述】:

我的 NSDocument 子类实现了 selectAll:。唯一的问题是,我使用的是 NSTableView,它还实现了 selectAll:。但是,NSTableView 中的 selectAll: 操作并没有达到我想要的效果,并且它确实阻止了我的 Document 类中的 selectAll: 方法在响应者链中被访问。

我已经有一个 NSTableView 的子类,经过一番探索后,我通过向我的 NSTableView 子类添加了一个 respondsToSelector: 方法,告诉它没有 selectAll: 操作,从而使事情按我想要的方式工作:

-(BOOL)respondsToSelector:(SEL)targetSelector

    if (targetSelector == @selector(selectAll:)) 
        return FALSE; // we don't want tableView's implementation of selectAll
    
    return [super respondsToSelector:targetSelector];

这似乎工作正常,允许我的文档子类中的 selectAll: 方法完成它的工作。但是这个解决方案让我有点不安。我在这个子类中实现的其他操作方法呢?我是否需要为每个人手动检查并返回 true ?我确实在这个子类中定义了两个动作,moveLeft: 和 moveRight:,它们似乎工作,即使我没有在 respondsToSelector: 中处理它们。所以我的问题是,我这样做是否正确,还是我缺少什么?或者也许有一些完全不同的方法可以正确地做到这一点?

顺便说一句,我从 OmniGroup 论坛上的这篇文章中得到了覆盖 respondsToSelector 的想法:

http://mac-os-x.10953.n7.nabble.com/Removing-an-action-from-a-subclass-td27045.html

【问题讨论】:

【参考方案1】:

super 发送消息会影响我们使用的该方法的实现。这不会改变self 是谁。

让我们试着想象一下respondsToSelector: 是如何工作的。给定一个选择器mySelector,它可能会自省从[self class] 开始的超类链上的每个类,以查看它是否真的实现 mySelector

现在,假设您的子类名为 MyTableView。当 MyTableView 说

[super respondsToSelector:targetSelector]

会发生什么?运行时会在父类链中查找respondsToSelector: 的另一个实现,最终会找到 NSObject 的原始实现。该实施有什么作用?好吧,我们刚刚回答了这个问题:它开始在[self class] 中搜索targetSelector 的实现。那仍然是 MyTableView 类!因此,如果您在 MyTableView 中定义了 moveLeft:respondsToSelector: 会找到它,并且会为 moveLeft: 返回 YES,这与您希望和期望的完全一样。

因此,概括地说,这个搜索被扭曲的唯一选择器是搜索selectAll: - 完全符合您的希望和期望。所以我认为你可以放松下来,相信你所做的不仅是可以接受和可行的,而且是你最初提出的问题的正常解决方案。

您可能还想查看 Apple 的 Objective-C 运行时编程指南消息转发一章。

【讨论】:

谢谢。我意识到向 super 发送消息不会改变 self 是谁,但我没有想到实际上内省类以查看方法是否实现的逻辑在 NSObject 中,最终将由我的打电话给超级,但这当然很有意义。

以上是关于从子类中移除一个动作的主要内容,如果未能解决你的问题,请参考以下文章

手机卫士03_手势动作_广播接收者应用

如何在Swift中正确地从父节点中删除SKSpriteNode的子类(要从数组中移除,屏幕上的空格......)?

如何使用 Swift 从 UITabBarController 的子类触发动作

如何使用Swift从UITabBarController的子类中触发动作

从 fetchedResultsController fetchedObjects 中移除一个对象

如何从JavaScript对象中移除一个属性