引用計數的原則
- 自己生成的對象自己持有
- 非自己生成的對象自己也可以持有
- 不再需要自己持有的對象時釋放
- 非自己持有的對象無法釋放
案例:
/*
* 自己生成並持有對象
*/
id obj1 = [[NSObject alloc] init];
/*
* 自己持有對象
*/
[obj1 release];
/*
* 釋放對象
針仍然被保留在變量obj1中
* 但對象一經釋放絕對不能被訪問
* /
/*
* 取得非自己生成的對象
*/
id obj2 = [NSMutableArray array];
/*
* 自己不持有對象
*/
[obj2 retain]; //ARC不需要這個操作,編譯器會自動幫我們實現。而MRC下需要。
/*
* 自己持有對象
*/
[obj2 release];
/*
* 釋放對象
*/
那麼[NSMutableArray array]這個方法是如何實現取得對象存在,而不持有對象的呢。其實是用到了autorelease方法。
-(id) object {
id obj = [[NSObject alloc] init];
[obj autorelease];
return obj;
}
autorelease與release的區別在於。release一個對象,該對象立馬釋放,而autorelease一個對象,該對象註冊到autoreleasepool中,pool結束時自動調用release。
- (id) autorelease {
[NSAutoreleasePool addObject:self];
}
因此上面的代碼可以如下表示
NSAutoreleasePool *pool = [[NSAutoReleasePool alloc]init];
id obj = [[NSObject alloc] init];
[obj autorelease];
[pool drain];
autoreleasepool是跟NSRunLoop聯繫在一起的。NSRunLoop每次循環過程中NSAutoreleasePool對象被生成或被廢棄。
另外還有一點就是當有大量的autorelease對象生成,而沒有被釋放時,就會造成內存不足。比如
for (int i = 0; i < 圖象數; ++i) {
/*
* 讀入大量圖像
* 大量產生autoreleae對象
* 沒有釋放造成內存不足
* /
}
解決方案就是在適當的地方自己生成、持有、廢棄autoreleasepool對象
for (int i = 0; i < 圖象數; ++i) {
NSAutoreleasePool *pool = [[NSAutoReleasePool alloc]init];
/*
* 讀入大量圖像
* 大量產生autoreleae對象
* /
[pool drain];
/*
* autorelease對象被釋放
*/
}