Swift Segue异常:调用指定Identifier Segue时偶现崩溃
首先我注意到一个关键矛盾点:你代码里调用的是**"ready"** segue,但崩溃提示的是当前ViewController(4ViewController)找不到"select" segue——这说明崩溃时,是VC4在尝试触发"select",而非你预期的VC3触发"ready"。结合你的场景,我整理几个高概率的排查方向:
1. 先定位触发"select" segue的源头
崩溃时一定要查看Xcode的调用栈,找到到底是谁调用了performSegue(withIdentifier: "select", ...)。因为你自己的代码里没有触发这个segue,肯定是其他逻辑(UI控件、监听回调、多线程混乱)导致的。
2. 检查UI控件的意外关联
- 打开Storyboard,仔细检查VC3上的所有控件(按钮、手势、TableViewCell等):确保没有任何控件意外关联到了"select" segue(毕竟"select"是VC1到VC3的,VC3不该有这个segue的出发端)。
- 再检查VC4上的所有控件:确认没有控件关联了"select" segue,VC4根本不存在这个segue,一旦触发必然崩溃。
3. 排查UserDefaults的监听逻辑
你在readyToGo()里修改了UserDefaults的"go"值,有没有其他地方(比如VC4的代码)监听了这个key的变化?比如用UserDefaults.didChangeNotification做了监听,然后在回调里错误地触发了"select" segue?如果是这样,当你同步UserDefaults后,VC4的监听回调被触发,就会导致崩溃。
4. 确保performSegue在主线程执行
performSegue是UI操作,必须在主线程调用。如果readyToGo()是在子线程被触发的(比如网络请求回调、后台任务),会导致UI状态混乱,甚至触发错误的segue。修改代码强制在主线程执行:
func readyToGo() { DispatchQueue.main.async { [weak self] in guard let self = self else { return } UserDefaults.standard.setValue(self.check, forKeyPath: "go") // 注:iOS 10+ 不需要手动调用synchronize(),系统会自动同步 // UserDefaults.standard.synchronize() self.performSegue(withIdentifier: "ready", sender: self) } }
5. 检查segue的重复触发或状态混乱
- 有没有可能
readyToGo()被多次调用?比如按钮点击事件和手势冲突、网络回调重复触发。可以加日志打印,追踪调用情况:
func readyToGo() { print("[DEBUG] readyToGo called on VC: \(self)") DispatchQueue.main.async { [weak self] in guard let self = self else { return } print("[DEBUG] Performing segue 'ready' from VC: \(self)") UserDefaults.standard.setValue(self.check, forKeyPath: "go") self.performSegue(withIdentifier: "ready", sender: self) } }
- 检查Storyboard的segue配置:确认VC3到Tabbar Controller的segue Identifier确实是**"ready"**(注意大小写敏感,比如"Ready"和"ready"是不同的);同时确认VC1到VC3的"select" segue出发端是VC1的控件,没有误关联到VC3。
6. 内存管理与ViewController状态问题
如果VC3被提前释放,但它的delegate、block或者闭包被VC4持有,可能导致VC4执行了VC3的残留逻辑,触发错误的segue。建议在VC3的deinit方法里加日志,确认它是否被正常释放,同时取消所有监听和回调:
deinit { print("[DEBUG] VC3 deinitialized") // 取消所有UserDefaults监听、定时器等 NotificationCenter.default.removeObserver(self) }
按照这个顺序排查,应该能找到问题的根源。
内容的提问来源于stack exchange,提问作者NewYorker

