首页 » iOS编程基础:Swift、Xcode和Cocoa入门指南 » iOS编程基础:Swift、Xcode和Cocoa入门指南全文在线阅读

《iOS编程基础:Swift、Xcode和Cocoa入门指南》12.1 Cocoa内存管理的原理

关灯直达底部

之所以要管理引用类型内存是因为对于引用类型对象的引用只不过是指针而已。被指向的真实对象占据着内存,当该对象产生时,我们需要为其留出这块内存;当该对象销毁时,我们需要显式清理这块内存。当对象实例化时,内存被预留出来,不过该如何清理内存,应该什么时候清理呢?

至少,当一个对象不再有其他对象指向它时,那么这个对象就应该被销毁。没有指针指向的对象是无用的对象;它会占据着内存,不过没有其他对象可以引用它。这叫作内存泄漏。很多计算机语言都是通过一种叫作垃圾收集的策略来解决这个问题的。通过周期性地沿着对象链进行清理,并销毁那些没有指针存在的对象来防止内存泄漏。不过在iOS设备上,垃圾收集是一种代价高昂的策略,其内存非常有限,处理器相对来说也比较慢(可能只有一个核心)。这样,我们就需要手工管理iOS中的内存,当不再需要某个对象时要能精确地销毁它。

上面所说的困难之处在于“精确”。对象销毁不能过早,也不能太迟。多个对象可能都会持有相同对象的指针(引用)。如果对象Manny与Moe都拥有指向对象Jack的指针,并且Manny通过某种方式告诉Jack现在就要销毁,那么可怜的Moe就会持有一个什么都不指向的指针(更糟糕的是指向了垃圾)。如果指针所指向的对象在指针不知情的情况下被销毁了,那么这个指针就叫作野指针。如果Moe随后通过该野指针向它认为还存在的对象发送了消息,那么应用就会崩溃。

为了防止野指针与内存泄漏的出现,有一种基于数字的手工内存管理策略,这个数字由每个引用类型的对象所维护,叫作其保持计数。原则就是其他对象可以增加或减少一个对象的保持计数,并且其他对象只能做这两件事情。只要对象的保持计数为正数,那么对象就会存在。其他对象都无法销毁另一个对象;相反,当对象的保持计数降为0时,它就会被自动销毁。

根据该策略,需要让Jack一直存在的每个对象都应该增加Jack的保持计数,当不需要Jack存在时则需要将其保持计数减1。只要所有对象都能很好地遵循这个策略,那么手工内存管理的问题就会迎刃而解:

·不会再有任何野指针,因为指向Jack的任何对象都会增加Jack的保持计数,这确保Jack会一直存在。

·不会再有内存泄漏,因为不需要Jack的任何对象都会减少Jack的保持计数,这确保Jack最终会被销毁(保持计数为0表示不再有对象需要Jack了)。