如何实现无内存泄漏的视图控制器重复工作流?
解决重复工作流的导航栈内存泄漏问题
核心思路
当C完成工作流要启动新的A时,直接把整个导航栈替换成新的A控制器,旧的A、B、C会因为失去强引用被自动回收,既保留当前工作流内的返回能力,又不会堆积历史控制器。
具体操作步骤
替换导航栈,不用performSegue跳转
在C控制器里,完成工作流后触发跳转的代码里,直接创建新的A实例,然后重置导航栈:// 假设A的storyboard ID是"AViewController" let newA = storyboard?.instantiateViewController(withIdentifier: "AViewController") as! AViewController navigationController?.setViewControllers([newA], animated: true)这个操作会把导航栈直接换成
[newA],旧的A、B、C会被ARC自动清理,不会留在栈里占内存,而且animated: true能保留跳转动画,和用segue的体验一致。排查残留的_childModalViewController
如果内存图里还能看到这个链,检查这两点:- 有没有用
present(_:animated:completion:)弹出过控制器但没调用dismiss(animated:completion:)?modal弹出的控制器如果不手动 dismiss,会一直被保留。 - 检查A、B、C里的闭包、代理有没有循环引用:比如代理没设成
weak,或者闭包捕获了self但没加[weak self],导致控制器无法被销毁。可以在每个控制器的deinit里加打印日志,确认是否被回收:
如果没看到对应打印,就说明有其他强引用没释放,得针对性排查。deinit { print("\(self) 被销毁了") }
- 有没有用
当前工作流内的返回不受影响
B返回A、C返回B依然用系统默认的返回按钮或者popViewController(animated: true)就行,完全不影响,因为新工作流的栈是独立的。
内容的提问来源于stack exchange,提问作者The Beruriah Incident
相关产品推荐
相关产品推荐

