内存泄漏排查
问题
App 使用一段时间后越来越卡,怀疑内存泄漏,如何排查?
答案
排查工具
| 工具 | 特点 | 使用场景 |
|---|---|---|
| Instruments → Leaks | 自动检测泄漏 | 开发阶段 |
| Instruments → Allocations | 查看内存增长 | 定位泄漏对象 |
| Memory Graph Debugger | Xcode 内置可视化引用图 | 查看循环引用 |
| MLeaksFinder | 自动检测 VC 泄漏 | 开发阶段自查 |
排查流程
- Xcode Memory Graph:Debug → Debug Memory Graph → 查找紫色感叹号
- 操作复现:进入页面 → 退出 → 检查 VC 是否释放(加
deinit打印) - Instruments Allocations:反复进出页面,看
# Living是否持续增长
常见泄漏场景
// 1. 闭包强引用 self
class ViewController: UIViewController {
var onComplete: (() -> Void)?
func setup() {
// ❌ 泄漏:闭包持有 self,self 持有闭包
onComplete = {
self.view.backgroundColor = .red
}
// ✅ 修复
onComplete = { [weak self] in
self?.view.backgroundColor = .red
}
}
}
// 2. Timer 强引用
// ❌ Timer 强持有 target
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(tick), userInfo: nil, repeats: true)
// ✅ 使用 block API
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] _ in
self?.tick()
}
// 3. NotificationCenter(iOS 9+ 自动移除,但闭包版要注意)
// ✅ 保存 token 并在 deinit 移除
常见面试问题
Q1: 如何自动检测退出页面后 VC 没有释放?
答案:MLeaksFinder 的原理:在 viewDidDisappear 后延迟 2 秒检查 VC 是否还存在。如果还存在就弹出警告。原理是 DispatchQueue.main.asyncAfter + weak 引用检测。也可以在基类 VC 的 deinit 中打印日志。