Swift中 Dismiss ViewController 后内存未释放问题咨询
解决重复跳转ViewController后的内存泄漏问题
兄弟,这种反复打开再关闭DetailViewController后内存持续飙升的情况,我踩过好多次坑,大概率是循环引用或者页面内的资源没及时清理导致的,咱们一步步来排查解决:
1. 先排查最常见的循环引用问题
循环引用会直接导致DetailViewController的deinit方法无法执行,内存永远释放不了,优先检查这几点:
- 闭包中的强引用:如果你的DetailViewController里有网络请求、异步回调这类闭包代码,一定要用
[weak self]或者[unowned self]打破循环:// 错误示例(会导致循环引用) APIManager.loadDetailData { result in self.refreshUI(with: result) } // 正确写法 APIManager.loadDetailData { [weak self] result in self?.refreshUI(with: result) } - 代理的强引用:如果DetailViewController用到了代理模式,必须把代理声明为
weak类型,因为UIViewController是引用类型,强引用代理会导致双向持有:// 正确的代理声明方式 protocol DetailViewControllerDelegate: AnyObject { func didFinishDetailOperation() } class DetailViewController: UIViewController { weak var delegate: DetailViewControllerDelegate? }
2. 检查页面内的资源是否及时释放
即使没有循环引用,如果页面内的资源没主动清理,也会导致内存占用居高不下:
- 定时器(Timer):如果用了Timer,一定要在页面销毁前调用
invalidate(),最好放在deinit里:class DetailViewController: UIViewController { var timer: Timer? deinit { timer?.invalidate() timer = nil print("DetailViewController 已销毁") } } - 通知观察者:如果通过
NotificationCenter注册了通知,一定要在deinit里移除观察者:deinit { NotificationCenter.default.removeObserver(self) } - 网络/下载任务:如果有未完成的URLSession任务,要在页面销毁前取消并置空引用:
class DetailViewController: UIViewController { var dataTask: URLSessionDataTask? deinit { dataTask?.cancel() dataTask = nil } }
3. 用Xcode工具精准定位泄漏点
如果上面的方法还没解决,直接用Xcode的Leaks工具排查:
- 打开Xcode,点击顶部菜单
Product > Profile(快捷键Command + I) - 在弹出的窗口中选择
Leaks,点击Choose - 运行App后,重复你的跳转操作50次左右,看Leaks面板里的红色标记,点击进去就能看到具体哪个对象没被释放,以及它的引用链,顺着链就能找到泄漏根源。
最后确认一个小细节
确保你在DetailViewController里调用的是正确的关闭方法:
// 正确的dismiss方式(如果是用present打开的) @objc func backButtonTapped() { dismiss(animated: true) }
不要混用push/pop和present/dismiss,否则可能导致页面栈混乱,间接引发内存问题。
内容的提问来源于stack exchange,提问作者Emre Önder
相关产品推荐
相关产品推荐

