UIWindow 子类:Touches 事件不会被触发

Posted

技术标签:

【中文标题】UIWindow 子类:Touches 事件不会被触发【英文标题】:UIWindow subclass: Touches event not get fired 【发布时间】:2016-08-31 15:51:27 【问题描述】:

我想在我当前的项目中实现会话时间功能。因此,我试图继承 UIWindow 并覆盖 touchesBegantouchesEnded 方法。

class BaseWindow: UIWindow 

    convenience init() 
        self.init(frame: UIScreen.mainScreen().bounds)
    

    private var sessionTimeOutTimer: NSTimer?

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) 
        sessionTimeOutTimer?.invalidate()
    

    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) 
        sessionTimeOutTimer = NSTimer.scheduledTimerWithTimeInterval(60, target: CIAppManager.sharedManger(), selector: #selector(CIAppManager.sessionTimeOut), userInfo: nil, repeats: false)
    

在应用委托中我这样做了

private let baseWindow = BaseWindow()
var window: UIWindow? 
    get 
        return baseWindow
    
    set 

但问题是 touchesBegantouchesEnded 没有被调用。我无法弄清楚我做错了什么。

【问题讨论】:

也许这个项目会对你有所帮助:github.com/marqeta/mqtimeout 请向我们展示您的整个 app delegate 文件,因为我对 private let baseWindow = ... 行的感觉非常糟糕,这似乎没有任何合理的用途,所以,请,整个文件会更健谈。 【参考方案1】:

不会为您的窗口调用touchesBegan(_:with:) API,除非没有其他人来捕获触摸事件。通常情况并非如此,因为您希望您的 UI 元素接收触摸。

您要在窗口子类中实现的是sendEvent(:_) 并将您的逻辑放在那里。不要忘记调用超级实现来传递事件。

使用这种方法的一个小问题是您会听到一些不是触摸事件的事件,但这可能不是问题,因为它们大多是用户生成的。

【讨论】:

【参考方案2】:

而不是继承UIWindow。您可以在AppDelegate 的窗口中添加UITapGestureRecognizer

let gestureRecogniger = UITapGestureRecognizer(target: self, action: #selector(yourSelector)) // Implement your selector
gestureRecogniger.cancelsTouchesInView = false
window?.addGestureRecognizer(gestureRecogniger)

如果您需要考虑除点击以外的其他触摸,请同时使用 UIPanGestureRecognizerUITapGestureRecognizer

如果您的子视图有自己的手势识别器,请添加此扩展

extension AppDelegate: UIGestureRecognizerDelegate 
    func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool 
        return true
    

然后做

gestureRecogniger.delegate = self

【讨论】:

这只会捕捉点击,而不是触摸。它也不能很好地与具有自己的手势识别器的子视图一起使用。 哇的反对票雨。 :) 令人惊讶的是,不同的人以不同的方式使用选票。无论如何..有办法解决你所说的问题。查看我的更新答案。【参考方案3】:

我尝试继承 UIWindow 并覆盖方法 touchesBegan, touchesEnded 当窗口有一个 rootViewController 检查演示项目时,这些方法被调用。 Sample app TouchTest

也检查这个方法 - (void)sendEvent:(UIEvent *)event

根据文档:您可以调用此方法将自定义事件分派到窗口的响应程序链。 窗口对象将触摸事件分派给发生触摸的视图,并将其他类型的事件分派给最合适的目标对象

【讨论】:

【参考方案4】:

跟踪会话的更好方法是注册UIApplication 通知,例如UIApplicationDidEnterBackgroundNotificationUIApplicationDidFinishLaunchingNotification

应用程序通知的完整列表位于UIApplication class reference 的底部。您可以创建一个会话跟踪器类来干净地监听这些,而不会干扰代码的其他部分。

【讨论】:

以上是关于UIWindow 子类:Touches 事件不会被触发的主要内容,如果未能解决你的问题,请参考以下文章

MvvmCross 6 中的子类 UIWindow

自定义 UIWindow 方向

Apple 文档在谈论其他哪些 UIWindow 接收触摸事件?

子类化 UIButton 并覆盖触摸事件 - 不起作用

为啥不在 UIViewController 子类中分配 UIWindow 对象呢?

UIResponder相关