跳到主要内容

内存泄漏排查

问题

App 使用一段时间后越来越卡,怀疑内存泄漏,如何排查?

答案

排查工具

工具特点使用场景
Instruments → Leaks自动检测泄漏开发阶段
Instruments → Allocations查看内存增长定位泄漏对象
Memory Graph DebuggerXcode 内置可视化引用图查看循环引用
MLeaksFinder自动检测 VC 泄漏开发阶段自查

排查流程

  1. Xcode Memory Graph:Debug → Debug Memory Graph → 查找紫色感叹号
  2. 操作复现:进入页面 → 退出 → 检查 VC 是否释放(加 deinit 打印)
  3. 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 中打印日志。

相关链接