Automatic Reference Counting(ARC)是iOS 4.0以上,在Xcode 4.2以上建立工程時可以選擇開啟的記憶體管理功能。看上去是可選擇功能,但開啟後對編程有較大影響,所以值得仔細考究一番。
首先,正如 Automatic Reference Counting名稱所表達的意思,自動引用計數並不是垃圾自動回收,並非如JavaScript中,只管聲明變數或成員,而由解譯器自動地決定其是否釋放。
在ARC下有如下限制:
release是不可調用的,
dealloc不可直接調用,並且不能[super dealloc]
唯一直觀的方法是
str=nil;
但即使如此,只是之後的代碼無法用str去引用原字串對象而已,原字串所用記憶體未必被釋放。如以下情況:
NSString *strTest = [[NSString alloc] initWithFormat:@"%@", @"One!!!" ];
NSString *strOwned = strTest;
strTest = nil;
NSLog(@”%@”, strOwned);
結果是輸出 One!!!
原因是所有聲明的對象,預設都是strong,只要對象被strong對象引用一次,count(實際對象計數器)就被加1,上例子中 strTest指向的@"One!!!"被strOwned引用了一次,即使自己被置為nil(ARC世界中表示release,count減一),count依然不為0,所以記憶體並沒有釋放,而直到 strOwned=nil的時候,@"One!!!"才真正被釋放。
這個釋放機制的過程在上面的簡單情況中還是很好理解的,那麼來看看下面的情況:
NSString *strTest = [[NSString alloc] initWithFormat:@"%@", @"One!!!" ];
NSString *strTest2 = [[NSString alloc] initWithFormat:@"%@", @"Two!!!" ];
NSString *strTest3 = [[NSString alloc] initWithFormat:@"%@", @"Three!!!" ];
NSString *strTest4 = [[NSString alloc] initWithFormat:@"%@", @"Four!!!" ];
NSString *strTest5 = [[NSString alloc] initWithFormat:@"%@", @"Five!!!" ];
NSString *strTest6 = [[NSString alloc] initWithFormat:@"%@", @"Six!!!" ];
NSString *strTest7 = [[NSString alloc] initWithFormat:@"%@", @"Seven!!!" ];
array = [[NSMutableArray alloc] init];
[array addObject:strTest];
[array addObject:strTest2];
[array addObject:strTest3];
[array addObject:strTest4];
[array addObject:strTest5];
[array addObject:strTest6];
[array addObject:strTest7];
在某處執行
[array removeAllObjects];
strTest~ strTest7是否被釋放?
回答這個問題首先要回答,array的對象是否被引用?
見如下聲明:
NSString *strOwned;
__weak NSString *strWeak;
__weak NSString *strWeak2;
NSString *strStrong;
strOwned = [array objectAtIndex:0];
strWeak = [array objectAtIndex:1];
strWeak2 = [array objectAtIndex:2];
strStrong = strWeak2;
以下輸出各是什嗎?
清單3
NSLog(@"%@", strOwned);
NSLog(@"%@", strWeak);
NSLog(@"%@", strWeak2);
NSLog(@"%@", strStrong);
執行
[array removeAllObjects];
之後,以上各輸出為:
這裡比較 strWeak 和 strWeak2的結果是比較有意思的,同樣是聲明為weak,strWeak2隻是被strong的strStrong引用過後,所用對象便也無法由來源(這裡是array)釋放了,這可能也是複雜工程中容易出錯的原因吧。
最後,如果array中各字串對象被另一個類的成員所引用,如下
myObj = [[MyObject alloc] init];
myObj.strStrong = strTest6;
myObj.strWeak = strTest7;
執行
[array removeAllObjects];
之後,清單3的執行結果又是如何呢?回答這個問題前,先考慮下 myObj本身是strong還是weak,情況有何不同?