Swift 4中Unwind Segue导致多层控制器误关闭的问题求助
你遇到的核心问题是模态栈层级关系与Unwind Segue的匹配逻辑冲突:当前你的模态栈结构是 MasterVC -> present -> CatalogueVC(TabBar) -> present -> AddCategorieVC,而CategorieVC是CatalogueVC的Tab子控制器,并非模态栈的直接父级。当触发Unwind Segue时,系统会从当前VC向上遍历模态栈,寻找第一个实现目标unwind方法的控制器——但因为CategorieVC不在模态栈的直接链路上,系统会跳过它,继续往上匹配到MasterVC,最终导致连CatalogueVC一起被dismiss。
下面给你两个可行的解决方案,优先推荐第一个,更灵活可控:
方案一:用闭包回调替代Unwind Segue传递数据
这种方式完全避开Segue的匹配问题,直接通过闭包在子VC和父VC间传递数据,同时只关闭当前的AddCategorieVC:
- 在AddCategorieVC中定义闭包属性
// AddCategorieVC.swift import UIKit class AddCategorieVC: UIViewController { // 定义闭包,用于传递保存的分类名称 var onSaveCompletion: ((String) -> Void)? // ... 其他现有代码 @IBAction func Btn_Save(_ sender: Any) { guard let categorieName = Txt_CategorieName.text, !categorieName.isEmpty else { // 可选:添加输入为空的提示,比如弹出alert return } // 调用闭包传递数据 onSaveCompletion?(categorieName) // 仅关闭当前VC,回到CategorieVC dismiss(animated: true, completion: nil) } }
- 在CategorieVC中设置闭包并处理保存逻辑
修改present AddCategorieVC的代码,添加闭包回调:
// CategorieVC.swift @IBAction func Btn_AddCategorie(_ sender: Any) { self.Mode = "New" guard let addCategorieVC = storyboard?.instantiateViewController(withIdentifier: "AddCategorieVC") as? AddCategorieVC else { return } // 设置闭包,接收从AddCategorieVC传来的名称并处理保存 addCategorieVC.onSaveCompletion = { [weak self] categorieName in guard let self = self else { return } if self.Mode == "New" { let myCategories = TblCategorie(context: self.Mycontext) myCategories.categorie_Name = categorieName do { try self.Mycontext.save() // 可选:添加刷新分类列表的代码,比如重新fetch数据 } catch { debugPrint ("保存出错:\(error.localizedDescription)") } } } present(addCategorieVC, animated: true, completion: nil) }
修改后,点击保存按钮只会关闭AddCategorieVC回到CategorieVC,同时执行闭包里的CoreData保存逻辑,完全不会影响CatalogueVC。
方案二:修复Unwind Segue的目标匹配
如果你坚持使用Unwind Segue,需要确保系统能正确找到CategorieVC里的unwind方法:
精准选择Unwind Segue的目标方法
从AddCategorieVC的保存按钮拖线到VC顶部的Exit图标时,在弹出的选项中务必选择CategorieVC里的FctSaveCategories方法,不要误选其他VC的同名方法。在CatalogueVC(TabBarController)中转发Unwind请求
因为CategorieVC是TabBar的子VC,系统可能无法直接识别到它的unwind方法,你需要在CatalogueVC中添加中转方法,手动将请求转发给当前选中的Tab子VC:
// CatalogueVC.swift(你的TabBarController) @IBAction func unwindToCatalogue(_ sender: UIStoryboardSegue) { // 将unwind请求转发给当前选中的子VC if let selectedVC = selectedViewController as? UIViewController, let unwindAction = selectedVC.value(forKey: "FctSaveCategories:") as? (UIStoryboardSegue) -> Void { unwindAction(sender) } }
然后在AddCategorieVC的Unwind Segue中选择这个unwindToCatalogue方法,系统会先到CatalogueVC,再转发给当前的CategorieVC执行保存逻辑。
不过这种方法相对繁琐,不如闭包回调直观可控,所以更推荐方案一。
内容的提问来源于stack exchange,提问作者Wael

