Swift中无法Push导航控制器:模态转导航视图遇报错问题
问题原因及解决方案
错误原因分析
- 推送导航控制器不被允许:报错
Thread 1: Pushing a navigation controller is not supported的直接原因是你尝试用pushViewController推送一个UINavigationController类型的实例(即contentView)。UINavigationController的pushViewController方法仅支持推送普通UIViewController子类实例,无法推送另一个导航控制器。 - 视图生命周期操作错误:你在调用
dismiss后才执行navInfoViewLoad(),此时InformationView已开始从视图层级移除,self.navigationController大概率已变为nil,即便不为空,在dismiss过程中操作导航栈也会触发异常。
修复步骤
步骤1:修正contentView类型
确保contentView是普通UIViewController子类,而非UINavigationController。若业务确实需要contentView带导航栏,应将其作为根控制器嵌入新的导航控制器后通过present展示,而非push。
步骤2:调整代码执行顺序
移除self.presentingViewController?.dismiss(animated: true)——你的需求是在当前模态导航栈内跳转至contentView,无需先关闭模态窗口。修改后的saveBtnClick方法如下:
@objc func saveBtnClick(sender: UIButton){ content.phoneName = self.nameField.text! content.phoneNum = self.phoneNumber.text! try! realm.write { realm.add(content, update: .all) } print(Realm.Configuration.defaultConfiguration.fileURL!) // 建议通过闭包/通知通知列表VC刷新,避免直接持有引用引发循环引用 // table.tableView.reloadData() navInfoViewLoad() }
步骤3:修正导航栈操作
确保navInfoViewLoad()中推送的是合法的UIViewController实例:
func navInfoViewLoad(){ let childVC = contentView // 确认contentView为UIViewController子类 self.navigationController?.pushViewController(childVC, animated: true) }
额外优化:列表刷新的正确方式
直接调用table.tableView.reloadData()存在循环引用风险,推荐用闭包回调或通知中心实现列表刷新:
- 闭包回调方式:在
InformationView中定义闭包属性,保存完成后触发:
// InformationView中添加闭包属性 var onDataSaved: (() -> Void)? // saveBtnClick中替换reload代码 onDataSaved?()
在列表VC的addBtnClick中设置闭包:
let childVC = InformationView() childVC.onDataSaved = { [weak self] in self?.tableView.reloadData() } let fakeRootView = UINavigationController(rootViewController: childVC) self.present(fakeRootView, animated: true)
内容的提问来源于stack exchange,提问作者Younsung
相关产品推荐
相关产品推荐

