与 C 有一点类似,oc 需要使用 alloc 方法申请内存。不同的是,c 直接调用 free 函数来释放内存,而 oc 并不直接调用 dealloc 来释放。整个 oc 都使用对象引用,而且每一个对象都有一个引用计数器。当计数器为 0 时,系统调用 dealloc 来释放内存。oc 提供了 autorelease 属性,从而可以让系统自动释放对象所占有的内存。
1. 基本的内存管理
因为 iPhone 运行环境没有垃圾回收机制,所以我们在为它开发一个应用程序的时候需要了解一些基本的内存管理方面的做法。
申请内存:(alloc)
当使用 alloc 创建了一个对象时,需要在用完这个对象后释放 (release)它,但如果该对象已经被设置为自动释放(autorelease)类型,则无需再去释放它,否则程序会报错。
释放内存 (dealloc)
当一个对象从内存上删除之前,系统就自动调用 dealloc 方法,这是释放成员变量的内存的最好时机,比如释放前面 alloc 的 name 和 address.
1 - (void)dealloc 2 { 3 [name release]; // 释放成员变量所占的内存 4 [address release]; // 同上 5 [super release]; // 这个非常重要,因为必须调用这个方法来让父类清除它自己,否则,这个对象将没有被清除干净,会造成内存泄漏。 6 }
在垃圾回收机制下, dealloc 不会被调用到,取而代之的是,需要实现 finalize 方法。
引用记数 (retainCount)
整个 oc 都使用对象引用,而且每个对象有一个引用计数器。当使用 alloc (或者 copy)方法创建一个对象时,其计数器的值为1。调用 retain 方法就增加 1,调用 release 方法就减少1。当计数器为0时,系统自动调用 dealloc 方法来释放内存中的对象。下面看一个实际的例子:
1 #import <Foundation/Foundation.h> 2 #import "Person.h" 3 4 int main() { 5 Person *p = [[Person alloc] init]; // 计数器的值默认为1. 6 int i1 = (int)[p retainCount]; // i1 = 1. 7 NSLog(@"i1 = %ld",i1); 8 9 [p retain]; // 计数器的值加1变为2. 10 [p release]; // 计数器的值减1变为1. 11 [p release]; // 计数器的值减1变为0,系统自动调用 dealloc 方法来释放内存中的对象。 12 return 0; 13 }
字符串的处理
如果alloc 或者 copy 了一个对象(比如字符串),那么,在方法结束的时候需要 release 或者 autorelease 这个对象。
类成员变量的处理
内存泄漏
为防止内存泄漏:我们必须遵循下面几个内存管理的基本原则:
1. 如果使用 alloc (或者 copy)方法创建一个对象,或者使用 retain 保留一个对象,那么,都要自己释放对象。
2. 在大多数情况下,申请内存的语句数量和释放内存的语句数量应该相等。
3. 尽量少使用内存,用完后立即释放。
垃圾回收 (Garbage-collection)
copy , nonatomic
对于字符串类型的属性变量,我们经常使用下面类似的语句:
@propery (nonatomic,copy) NSString *name; 它就等价与
现在新的 Xcode 版本中已经不需要我们人工去管理内存了,而是引用了ARC 内存管理机制:
对于ARC机制的使用,苹果发布了几条重要的规则需要开发者遵守。单单看那些生搬硬套的东西难免生涩,根据开发经验将规则总结如下:
(1)不能调用dealloc,不能重写和调用retain,release,retainCount 和autorelease,同理,@selector(retain),@selector(release)这些曲线救国的方法也不能调用。 dealloc虽然能够重写,但是不能调用[super dealloc]之类的方法,CoreFoundation框架由于非从属cocoa框架,所以CFRetain和CFRelease仍然正常使用。
(2)不能使用NSAllocateObjec或NSDeallocateObject函数来创建对象
(3)不能在C语言的结构体中使用对象指针,同时建议用object-c的类来管理数据而不是结构体
(4)不得使用NSAutoreleasePool对象。ARC中,全部使用@autorelease关键字代替,且比NSAutoreleasePool更高效
(5)不得使用内存Zone,那些牵涉NSZone的方法都不得使用。
(6)不得对一个属性变量的取值方法命名以new开头
(7)outlet均用weak关键字修饰,除非他是xib中最顶部的界面元素,则需要strong。
(8)Core Foundation不适合ARC,该创建的仍创建,该释放的仍释放。
ARC新增关键字
ARC新增两个武功高强的左右护法:strong 和 weak
strong的含义和retain相同,weak和assign相同,修饰完的属性变量用法也是完全没有改变,不过strong和weak只能修饰对象。
苹果官方对于ARC机制中对象的内存引用规则:
(1)任何对象,如果仍有持有者,就不会销毁
(2)任何对象,已经没有任何持有者,即自动销毁
持有者就是指向对象的指针,如果是strong修饰的,即是对象的持有者,如果是weak属性的,则不是持有者。