先簡單解釋一下nil和release的作用:nil就是把一個對象的指標置為空白,只是切斷了指標與記憶體中對象的聯絡;而release才是真正通知記憶體釋放這個對象。所以nil並沒有釋放記憶體,只有release才回真正釋放記憶體。一個對象在release之後,給它所分配的記憶體就已經被釋放了,如果釋放之後系統再用到這個對象,那麼程式就會crash。如果釋放之後把它的指標置為空白,則即便後面的程式用到該對象,也不會崩潰。如果沒有release就直接把對象置為nil,retaincount等於0,會發生記憶體泄露。
類的成員變數,定義屬性為retain,之後給此成員變數賦值的時候要引用self.調用此變數。但是在alloc的時候不要引用self.來給此變數賦值。
例如:self.m_strTest = [[NSString alloc]init];是錯誤的。正確的應該是m_strTest
= [[NSString alloc]init];
用類方法初始化一個對象時,對象的retaincount是1.
比如
searchButton = [UIButtonbuttonWithType:UIButtonTypeCustom];
此時searchButton的retaincount是1,但是不用自己release。
當你往數組裡面添加一個對象時。數組裡面儲存的並不是這個對象的拷貝,而只是一個指向該對象的指標。數組在儲存
這個指標的同時會向指標所指的對象發送一個retain訊息,相應的,對象的持有計數會增加。將對象從數組中移除的時候,同樣會向對象發送release 訊息,對象的持有計數會減小。當我們釋放這個數組時,會向儲存在這個數組中的所有對象發送release訊息。看下面的兩個例子:
1、沒有釋放記憶體的版本
array = [[NSMutableArray alloc] init];
for ( i = 0; i < 10; i++) {
newNumber = [[NSNumber alloc]initWithInt:(i * 3)];
[array addObject:newNumber];
}
上面的代碼在建立newNumber對象時,向對象的發送了retain訊息,對象的持有計數變為1。當向array中添加這個對象的引用時,又向對象發送 了一次retain訊息,這樣對象的持有計數就變為2了,在使用完array時,我們會習慣性的釋放掉array,但這樣並不會釋放array所持有的對
象,而只是使所有對象的持有計數變為1,這些對象依然會佔用著記憶體。
2、釋放記憶體的版本
for (i = 0; i < 10; i++) {
newNumber = [[NSNumber alloc]initWithInt:(i*3)];
[array addObject:newNumber];
[newNumber release];
}
NSString* test = [[NSStringalloc]initWithFormat:@"%@",@"hello"];
NSLog(@"after alloc=%d",[testretainCount]);//1
[test retain ];//2
NSString* test2 = test;
[test2 retain];
NSLog(@"after retain=%d",[test retainCount]);//3
NSMutableArray* array = [[NSMutableArrayalloc]init];
[array addObject:test];
NSLog(@"after retain=%d",[testretainCount]);//4
[array removeObjectAtIndex:0];
NSLog(@"after array removeObjectAtIndex=%d",[test retainCount]);//5
// [array removeAllObjects];
//NSLog(@"after array removeAllObjects=%d",[testretainCount]);//5
if (1==[test
retainCount]) //release和nil應該這樣寫,這樣就會防止亂用nil發生記憶體泄露,也會防止release之後再實用此對象發生crash
{
[test release];
test= nil;
}
else
{
[test release];
}
if (test)
{
NSLog(test);
}
NSString* test = [[NSStringalloc]initWithFormat:@"%@",@"hi"];
[test release];
[test release];//出錯(message sent to deallocated instance),因為test已經被release了.