花时间整理一下 iOS 开发中内存泄漏相关的知识,以备后续查阅。

什么是内存泄漏

是计算机科学中的一种资源泄漏,主因是计算机程序的内存管理失当,因而失去对一段已分配内存空间的控制,程序继续占用已不再使用的内存空间,或是存储器所存储之对象无法透过执行代码而访问,令内存资源空耗。 –WikiPekia

内存泄露的危害

  • 增加了应用不必要的内存消耗
  • 可用内存变小,甚至耗光
  • 造成应用crash

如何发现内存泄漏

iOS开发中造成内存泄漏的常见原因是循环引用,所以探测循环引用成为发现内存泄漏的主要方向。

IDE提示循环引用

Xcdoe提示内存泄漏

Instruments工具检测

Instruments 是 Xcode 自带的一个检测调试工具,可以分析应 App 运行时 CPU、内存、网络、能耗、渲染等使用或表现情况,有助于开发者调试问题原因、优化 App 性能表现。 Instruments

Instruments调试循环引用

第三方SDK在运行时动态检测循环引用

如 facebook 的 FBRetainCycleDetector

常见的循环引用及避免

对象循环强引用

循环强引用 上面这段代码运行后的 Instruments 检测结果循环引用如下 检测结果循环引用

如何解决? 对象循环强引用的处理

block 循环引用

block循环引用 Instruments 分析循环引用如下 block循环引用结果

可以使用弱引用testCase来打破循环引用 block循环引用解决

NSTimer 循环引用

NSTimer循环引用

为什么这个会循环引用?

根据苹果描述,timer 实例会对target参数强引用,又因为self强持有timer,所以构成了循环引用 NSTimer循环引用原因

如何解决? 可以通过NSProxy来解决,但是感觉有点麻烦,不如下面这个方法简单直观。 通过换用另一个使用block作为参数的方法,在block中对self进行弱引用 避免NSTimer循环引用

Instruments看不到stack trace

The issue was due to a .dSYM file generated by Xcode as part of the build. The file is used in debug mode to symbolicate method calls. Instruments doesn’t seem to be aware of its location. In order to fix that I had to do the following:

  • Before starting to record under Instruments, go to File->Symbols
  • Unfold your app item and select your app name
  • Click “Locate” in front of dSYM path
  • the dSYM file corresponding to the app should be under ~/Library/Developer/Xcode/DerivedData/Build/Products/Debug-iphoneos/[APP_NAME].app.dSYM.
  • A dialog should pop up asking you whether Instruments should always look for dSYM files under that location; that’s what you want
  • Start recording; your method calls should now display properly

Absent Method Calls in Instruments Stack Trace

最后

判断是否存在循环引用就要看能否找出循环引用链,能找到即是存在。

循环引用的情况有很多,解决起来无非就一个原则,找出循环引用链,然后打破这个循环引用链即可。

未完待续。。。