Chapter 4 : 内存管理
1. NSAutoreleasePool : 自动释放池。
-> 程序可以有多个自动释放池(NSAutoreleasePool)
-> 自动释放池(NSAutoreleasePool)并不包含实际的对象(object/instance)本身,只是包含对释放的对象(object/instance)的引用。
-> 通过对目前的自动释放池(NSAutoreleasePool)发送一条autorelease消息,可将一个对象(object/instance)添加到其中。
// 自动释放池 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [pool drain];
2. 引用计数(Retain Count) : 创建对象(object/instance)时,将其引用计数设置为1,每次必须保持此对象(object/instance)时,就发送一条retain消息,使其引用计数加1。
[instance retain];
当不再需要此对象(object/instance)时,通过发送release消息,使其对象(object/instance)引用计数减1.
[instance release];
PS : 当引用计数(Retain Count)为0的时候,系统就会释放它的内存,通过向对象(object/instance)发送dealloc消息。
所以应该这样理解,dealloc是提供给系统来调用的,你不需要去手动的调用一个对象的dealloc。
// 获取一个对象(object/instance)的引用计数 // 返回类型为NSInteger [instance retainCount];
只要对象(object/instance)的引用计数不为0,系统就不会释放对象(object/instance)使用的内存。
PS :
-> 将对象(object/instance)添加到任何类型的集合(如:NSArray, NSDictionary)中都会使该对象(object/instance)的引用计数增加。而从集合中删除对象(object/instance)则会使引用计数减少。
-> 常量字符串没有引用计数机制,因为永远不能释放这些对象(object/instance)。
示例代码 :
int main(int argc, const char *agrv[]) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // Retain Count : 1 RetainTracker *tracker = [[RetainTracker alloc] init]; // Retain Count : 2 [tracker retain]; // Retain Count : still 2 [tracker autorelease]; // Retain Count : 1 [tracker release]; NSLog(@"releasing pool"); // Get nuked, sends release to tracker [pool release]; return 0; }
3. 访问方法(set and get)中的保留和释放:
原则如下:保持新的,释放旧的,谁拥有对象谁就负责释放对象
- (void)setEngine:(Engine *)newEngine { [newEngine retain]; // 类成员属性 [engine release]; engine = newEngine; }
4. 内存管理规则:
内存管理规则摘要:
-> 不再使用创建或保持的对象时,释放它们。释放对象,可以释放其所占的内存。
-> 发送release消息不一定能销毁对象,只有Retain Count为0时,系统才会向对象发送dealloc消息来释放它所占的内存。
-> 自动释放池(NSAutoreleasePool)在释放其本身时会自动释放池中的对象。实际细节是,系统向池中的每个对象发送一条
release消息,对引用计数为0的对象发送一条dealloc消息来释放它所占的内存。
-> 如果在某一方法中不再需要一个对象,但需要返回它,可发送一条autorelease消息来将此对象加入到自动释放池中以防止产生内存泄漏(Memory Leak)。
-> 若使用alloc或copy方法(或使用allocWithZone:、copyWithZone:或mutableCopy方法)来直接创建对象,则由你负责释放它。每次retain对象时,都应该release或autorelease。
-> 除上术规则中提到的方法外,不必释放其他方法返回的对象,这不是你的责任。