如何从同根ViewController C跳转至B且保留根控制器A?
嘿,这个跳转问题我之前也帮开发者解决过,刚好适配你的场景!核心要解决的是**从C到B无缝跳转、释放C、保留A的活跃状态(支持B unwind回A)**这几个点,给你两个可行的方案:
方案一:利用Unwind Segue + 转场协调器实现无缝衔接
这个方案能让两个转场(C→A、A→B)无缝融合,用户完全看不到A的界面:
在A中定义基础Unwind方法
先给A添加一个用于unwind的方法,后续B和C都可以通过这个方法回到A:@IBAction func unwindToA(_ segue: UIStoryboardSegue) { // 这里不需要额外逻辑,只是作为unwind的入口 }给C配置Unwind Segue到A
在Storyboard中,选中C的任意控件(比如按钮),拖拽到顶部的Exit按钮,选择刚才的unwindToA:方法,给这个segue设置一个标识符(比如unwindFromCToA)。在A的Unwind方法中触发到B的跳转
修改A的unwindToA:方法,利用转场协调器在unwind完成后立即触发到B的segue,确保动画无缝:@IBAction func unwindToA(_ segue: UIStoryboardSegue) { // 判断是从C过来的unwind if segue.source is CViewController { self.transitionCoordinator?.animate(alongsideTransition: nil) { [weak self] _ in guard let self = self else { return } // 触发A到B的segue(记得给这个segue也设置标识符,比如`segueAToB`) self.performSegue(withIdentifier: "segueAToB", sender: self) } } }在C中触发跳转
当你需要从C跳转到B时,直接调用unwind segue即可:func navigateToB() { performSegue(withIdentifier: "unwindFromCToA", sender: self) }
方案二:代码手动控制Dismiss + Present(更灵活)
如果不想依赖Storyboard的segue,可以用代码直接控制转场,同样能实现无缝效果:
- 在C中编写跳转逻辑
直接dismiss C,在dismiss的完成回调中让A present B,同时调整动画参数让衔接更自然:func goToB() { // 先dismiss C,动画保持开启 self.dismiss(animated: true) { // 获取根VC(也就是A) guard let aVC = UIApplication.shared.keyWindow?.rootViewController as? AViewController else { return } // 从Storyboard实例化B let bVC = aVC.storyboard?.instantiateViewController(withIdentifier: "BViewController") as! BViewController // 给B设置和C相同的modal转场样式,保证动画一致 bVC.modalPresentationStyle = self.modalPresentationStyle bVC.modalTransitionStyle = self.modalTransitionStyle // present B aVC.present(bVC, animated: true, completion: nil) } }
关键注意点
- 不管用哪个方案,B的unwind回A的逻辑和普通情况完全一致:在Storyboard中给B添加指向A的unwind segue即可,完全不影响。
- 方案一中的转场协调器(
transitionCoordinator)是关键,它能确保两个转场动画无缝衔接,不会出现A短暂显示的问题。 - 两种方案都会正确释放C,因为dismiss/unwind后C的引用会被清除,ARC会自动回收它。
内容的提问来源于stack exchange,提问作者Joey Slomowitz
相关产品推荐
相关产品推荐

