Objective-C(主要)使用引用计数内存模型。有手动引用计数和自动引用计数(ARC)。
ARC 的工作原理
如果您曾经使用过手动引用计数并运行过 clang 静态分析器工具,您会发现它在查找内存泄漏方面做得非常出色。这就是 ARC 背后的想法——如果分析器能够很好地发现泄漏,那么为什么不让它执行内存管理呢?
因此,分析是在编译时完成的,并且生成的代码使用保留和释放调用进行检测。这是 ARC 的基础及其出色的内存模型,在性能和易用性之间取得了良好的平衡。它在移动计算中特别有用,因为与垃圾收集不同,它不需要任何额外的 CPU 周期或电池消耗。
(注意:ARC 还引入了弱引用,这是一种在运行时将悬空指针归零的方法)。
使用 ARC 并不像垃圾收集那么简单——你仍然需要知道引用计数内存模型是如何工作的。可能会出现以下问题。
保留周期
内存泄漏的主要原因是保留周期。这就是对象 A 对对象 B 的引用,而对象 B 对对象 A 的引用的地方。例如,AirlineFlight 包含一名乘客,而乘客有一个 AirlineFlight -> 内存泄漏。
这在 Cocoa 中很常见。另一个例子是一个 ViewController 拥有一个视图,而这个 View 有一个委托,也就是 ViewController。听起来有点熟?
为了避免保留循环,其中一个对象必须不保留另一个。最常见的方法是将一个指定为父级,另一个指定为子级。父母保留孩子,但孩子不保留父母。例子:
视图控制器
@interface MyViewController
@property (nonatomic, strong) MyView* view
@end
看法
@interface MyView
@property (nonatomic, assign) MyViewController* controller
@end
保留周期现在被打破,内存泄漏将不再发生。
悬空指针
上面的例子不再有内存泄漏,但会导致另一个问题——悬空指针。视图控制器可能会消失,而视图仍然具有对控制器的引用。现在对控制器的任何调用都会导致崩溃。
有两种方法可以解决这个问题:
在 dealloc 方法中消除对控制器的引用。. . 但可能只是
使用弱引用,如下:
@property (nonatomic, weak) MyViewController* controller
iOS 5 及更高版本(或 OSX 10.7)有一个小的运行时实用程序,可以跟踪悬空指针并为您消除它们 - 这些被称为弱引用。
寻找内存泄漏
有几种方法。
- 使用 clang 静态分析器来检测保留周期。
- 使用仪器工具
- 我喜欢将日志语句放在我的控制器和其他关键类的 dealloc 方法中,以确保它们被释放。
寻找悬空指针
- 使用环境变量 NS_ZOMBIES_ENABLED 进行编译(或在 Xcode 中编辑 Scheme 并单击复选框,它将为您设置此参数)。
自动释放池
另一个可能发生的问题是在运行循环中分配了太多对象。. 要更正此问题,您可以在主池中创建另一个自动释放池。
@autoreleasepool
{
}
(在你的情况下,我认为这不是问题)。