You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在控制器基类检测用户交互以实现指定页面session超时,无需子类化UIApplication

实现方案

你可以通过基类添加兼容型全局手势+事件传递链适配的方式实现需求,不需要子类化UIApplication,具体实现逻辑如下:


方案1:基类添加穿透型全局手势(推荐)

这种方式可以覆盖99%的交互场景,且不会影响原有页面的交互逻辑:

  • 首先在公共基类控制器的viewDidLoad方法中添加手势识别器,设置cancelsTouchesInView = false避免拦截原有交互:
// Swift 示例
override func viewDidLoad() {
    super.viewDidLoad()
    // 添加通用手势识别器
    let monitorGesture = UITapGestureRecognizer(target: self, action: #selector(resetInactivityTimer))
    monitorGesture.cancelsTouchesInView = false
    monitorGesture.delegate = self
    self.view.addGestureRecognizer(monitorGesture)
    
    // 如果需要覆盖滑动、滚动类交互,可额外添加UIPanGestureRecognizer、UISwipeGestureRecognizer,配置规则同上

    // 初始化超时计时器
    setupTimer()
}
  • 实现手势代理方法,允许和页面原有手势同时触发,解决冲突问题:
extension BaseTimeoutViewController: UIGestureRecognizerDelegate {
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}
  • 计时器逻辑实现:
private var inactivityTimer: Timer?
// 可自定义超时时长,示例为5分钟
private let timeoutThreshold: TimeInterval = 300

private func setupTimer() {
    inactivityTimer = Timer.scheduledTimer(withTimeInterval: timeoutThreshold, repeats: false, block: { [weak self] _ in
        // 触发超时逻辑
        self?.handleSessionTimeout()
    })
}

@objc private func resetInactivityTimer() {
    // 重置计时器
    inactivityTimer?.invalidate()
    setupTimer()
}

private func handleSessionTimeout() {
    // 你的超时业务逻辑,比如弹出提示、退回登录页等
}
  • 页面消失时销毁计时器避免内存泄漏:
override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    inactivityTimer?.invalidate()
    inactivityTimer = nil
}

方案2:补全触摸事件捕获

如果需要覆盖非手势类的触摸交互,可以重写基类的UIResponder触摸方法,和方案1结合使用补全场景:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesBegan(touches, with: event)
    resetInactivityTimer()
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesMoved(touches, with: event)
    resetInactivityTimer()
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesEnded(touches, with: event)
    resetInactivityTimer()
}

注意:该方法无法捕获UIControl类控件(按钮、开关等)的点击事件,因为控件会优先消费触摸事件不会向上传递,需要搭配方案1的手势使用。

内容的提问来源于stack exchange,提问作者Shruti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 11:24:02