如何阻止SceneKit中的SpriteKit覆盖层捕获所有键盘按下事件
问题
我有一个运行正常的SceneKit视图,其视图控制器通过重写keyDown(with event: NSEvent)方法获取并管理键盘按下事件。但添加如下SpriteKit覆盖层后:
let skScene = MySKScene(fileNamed: "Level1.scnassets/3_overlay.sks")! scnView.overlaySKScene = skScene skScene.isUserInteractionEnabled = false
SKScene会捕获所有键盘按下事件(Level1.scnassets/3_overlay.sks只是一个空场景)。我通过以下代码追踪事件:
class MySKScene: SKScene { public override func keyDown(with event: NSEvent) { print("I reach here !") print(" isUserInteractionEnabled: \(self.isUserInteractionEnabled)") func printResponderChain(indent: String, resp: NSResponder) { print(indent + "type: \(type(of: resp))") if let father = self.nextResponder { printResponderChain(indent: indent + " ", resp: father) } } printResponderChain(indent: "", resp: self) } }
得到如下输出:
I reach here ! isUserInteractionEnabled: false type: MySKScene
此时SKScene出现矛盾情况:1. keyDown方法被调用;2. isUserInteractionEnabled为false;3. 响应链仅包含SKScene本身。请问如何完全禁用该SKScene?
解决方案
方法1:阻止SKScene成为第一响应者
在MySKScene类中重写canBecomeFirstResponder属性并返回false,系统就不会将键盘事件分发给它:
class MySKScene: SKScene { override var canBecomeFirstResponder: Bool { return false } // 你已有的其他代码... }
方法2:修复响应链并传递事件
首先手动设置SKScene的nextResponder为SceneKit视图,让事件能继续传递到后续响应者:
let skScene = MySKScene(fileNamed: "Level1.scnassets/3_overlay.sks")! scnView.overlaySKScene = skScene skScene.isUserInteractionEnabled = false skScene.nextResponder = scnView // 添加这行
然后在MySKScene的keyDown方法中调用super,让事件沿着响应链继续传递:
public override func keyDown(with event: NSEvent) { super.keyDown(with: event) }
方法3:移除不必要的事件重写
如果你的SKScene完全不需要处理任何键盘事件,直接删除keyDown方法的重写即可。同时保持isUserInteractionEnabled = false,配合方法1的canBecomeFirstResponder设置,就能彻底阻止它捕获键盘事件。
内容的提问来源于stack exchange,提问作者AirXygène
相关产品推荐
相关产品推荐

