为什么这个UIViewController成为第一响应者?

时间:2015-12-12 14:05:08

标签: ios swift uiviewcontroller first-responder motionevent

我已经基于XCode" 单一视图应用程序"创建了一个新的iOS应用程序。模板并仅修改了UIViewController

class ViewController: UIViewController {
    override func canBecomeFirstResponder() -> Bool {
        return false
    }

    override func motionBegan(motion: UIEventSubtype, withEvent event: UIEvent?) {
        print("motionBegan")
    }
}

问题在于,当我摇动设备时,尽管motionBegan返回canBecomeFirstResponder,但仍会调用false函数。

AFAIK应该在响应者链中的motionBegan上调用UIResponder(在这种情况下,从第一响应者开始,因为我们正在谈论非触摸事件)。

我的问题是:

  • " 单一视图中的初始第一响应者是什么 应用"申请开始后? (它是UIViewController view中最后添加的子视图吗?)
  • 设置初始第一响应者的对象是什么?

2 个答案:

答案 0 :(得分:1)

设置初始第一响应者的对象是什么?

设置初始第一响应者的对象是UIWindow。

From the Event Handling Guide for iOS:

  

动作和遥控事件。使用这些事件,窗口对象   将摇动或遥控事件发送给第一个   响应者处理。第一个响应者在The中描述   响应者链由响应者对象组成。

应用程序启动后“单一视图应用程序”中的初始第一响应者是什么? (它是UIViewController视图中最后添加的子视图吗?)

要设置的初始第一响应者必须发生一个事件,在这种情况下是视图控制器,因为它会覆盖动作开始方法。

事件由Responder Chain机制处理,并一直传递,直到找到一个可以处理它的对象。触摸事件和动态事件的路径略有不同,请参阅Event Handling Guide for iOS中的事件传递:响应者链了解详细信息。

您似乎正在关注Detecting Shake-Motion Events with UIEvent中的信息。哪种状态可以覆盖这两种方法。

    override func canBecomeFirstResponder() -> Bool {
    return false
}

override func motionBegan(motion: UIEventSubtype, withEvent event: UIEvent?) {
    print("motionBegan")
}

我做了一个与你的相同的快速测试应用,并注意到设置'canBecomeFirstResponder()'对视频控制器是否处理了动作事件没有承担

答案 1 :(得分:0)

实际上,您的视图控制器并未成为第一个响应者。根据{{​​3}}的文档,只要您覆盖此函数并返回false,在这种情况下,您就不会成为第一个响应者。

如果您尝试将以下内容放在代码中,例如,在motionBegan函数中,您会看到它在收到动作事件时显示它确实不是第一个响应者。

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    print("touchesBegan")          // OUTPUT: touchesBegan
    print(isFirstResponder())      // OUTPUT: false
}

这个函数仍然被调用的原因是因为没有第一个响应者可以处理它甚至代码中的任何其他地方。根据Apple关于canBecomeFirstResponder的文档:

  

动作事件使用响应者链来查找可以处理事件的对象。当用户开始摇动设备时,iOS会将第一个动作事件发送给第一个响应者。如果第一响应者没有处理该事件,则它会在响应者链上向上进行。

如果您想了解更多关于响应者链的信息,我建议您再做一些阅读Motion Events,它解释了如何设置链以及如何传递事件。

here