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

iOS16.4无导航控制器下,长按手势触发Segue跳转VC出现视图层级错误

问题分析与解决方案

问题根源

  1. 重复添加长按手势:在viewWillAppear中每次视图出现都会创建并添加新的UILongPressGestureRecognizer,导致视图绑定多个相同手势,触发时多次调用跳转逻辑,还会和系统手势冲突,引发SystemGestureGate超时错误。
  2. 未处理手势状态:长按手势的回调会在手势开始、变化、结束等多个阶段触发,直接调用performSegue会在视图层级未稳定的时机执行跳转,导致view is not in the window hierarchy错误。
  3. Segue触发时机不当:未在手势的正确阶段触发跳转,进一步加剧了视图层级问题。

解决步骤

1. 避免重复添加手势

将手势的创建与添加移至viewDidLoad(仅执行一次),而非viewWillAppear:

class V1: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let longPressGesture = UILongPressGestureRecognizer(
            target: self,
            action: #selector(cellWasPressed(_:))
        )
        longPressGesture.minimumPressDuration = 1.0
        view.addGestureRecognizer(longPressGesture)
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        // 移除原有的手势添加代码
    }
    
    // ... 其他代码
}

2. 仅在手势的正确状态触发跳转

修改回调方法,接收手势参数,仅在手势开始(.began)或结束(.ended)阶段执行跳转(按需选择):

@objc func cellWasPressed(_ gesture: UILongPressGestureRecognizer) {
    // 仅在长按达到时长时触发跳转
    guard gesture.state == .began else { return }
    
    performSegue(withIdentifier: "V2", sender: nil)
}

3. 验证Segue配置正确性

检查Storyboard中的Segue设置:

  • 确认Segue的Identifier为"V2",与代码完全一致。
  • 确认Segue类型为Present Modally(无需导航控制器),且Segue是从V1控制器本身(而非其子视图)拖拽至V2控制器,确保跳转由V1发起。

额外验证(可选)

若问题仍存在,可在跳转前验证V1的视图是否处于窗口层级:

@objc func cellWasPressed(_ gesture: UILongPressGestureRecognizer) {
    guard gesture.state == .began else { return }
    
    guard view.window != nil else {
        print("V1视图未加入窗口层级")
        return
    }
    
    performSegue(withIdentifier: "V2", sender: nil)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 22:05:15