Swift导航栈复用视图控制器问题:如何重置栈并加载全新viewcontroller1
解决方案
你可以通过UINavigationController的setViewControllers(_:animated:)方法实现重置导航栈的需求,该方法会直接替换整个导航栈的控制器列表,旧控制器会被自动释放,不会复用原有实例。根据你需要的动画效果,可以选择以下两种实现方案:
方案1:保留普通push的推入动画
如果需要和之前页面跳转一致的从右侧推入的动画,可以先执行push操作,之后立刻替换导航栈:
// 1. 实例化全新的viewcontroller1实例 let newVC1 = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "viewcontroller1") as! viewcontroller1 // 2. 配置导航栏属性 newVC1.navigationItem.setHidesBackButton(true, animated: false) // 注意:此处target改为newVC1自身,需将closeAction方法移到viewcontroller1类内部实现,避免后续野指针崩溃 newVC1.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Close", style: .done, target: newVC1, action: #selector(newVC1.closeAction)) // 3. 执行push动画 self.navigationController?.pushViewController(newVC1, animated: true) // 4. 动画完成后重置导航栈,仅保留新的viewcontroller1实例 DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [weak self] in self?.navigationController?.setViewControllers([newVC1], animated: false) }
方案2:使用类似返回的弹出动画
如果不需要push动画,要和普通返回操作一致的从左侧弹出动画,可以直接替换导航栈,代码更简洁:
let newVC1 = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "viewcontroller1") as! viewcontroller1 newVC1.navigationItem.setHidesBackButton(true, animated: false) newVC1.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Close", style: .done, target: newVC1, action: #selector(newVC1.closeAction)) // 直接替换整个导航栈,自带pop返回动画 self.navigationController?.setViewControllers([newVC1], animated: true)
注意事项
- 代码中的
viewcontroller1类名首字母小写不符合Swift编码规范,建议修改为ViewController1,避免后续编译或赋值时出现歧义 - 原有代码中UIBarButtonItem的target是当前发起跳转的控制器,导航栈重置后旧控制器会被释放,点击Close按钮会触发野指针崩溃,因此建议将
closeAction的实现放到viewcontroller1类内部,target设置为新创建的newVC1自身
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

