iOS16.4无导航控制器下,长按手势触发Segue跳转VC出现视图层级错误
问题分析与解决方案
问题根源
- 重复添加长按手势:在
viewWillAppear中每次视图出现都会创建并添加新的UILongPressGestureRecognizer,导致视图绑定多个相同手势,触发时多次调用跳转逻辑,还会和系统手势冲突,引发SystemGestureGate超时错误。 - 未处理手势状态:长按手势的回调会在手势开始、变化、结束等多个阶段触发,直接调用
performSegue会在视图层级未稳定的时机执行跳转,导致view is not in the window hierarchy错误。 - 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
相关产品推荐
相关产品推荐

