1. ARC並不是自動管理記憶體,與AutoreleasePool不同,ARC是LLVM 3.0編譯器提供的特性,編譯器自動在適當的地方插入retain、release、autorelease,所以還是手動管理記憶體,對象不會像AutoreleasePool一樣在記憶體中存放很久。
2. ARC只能工作於Objective-C對象,如果應用使用了Core Foundation或malloc()/free(),此時需要你來管理記憶體。
3. 雖然ARC管理retain和release,但並不表示不需要處理記憶體問題,strong指標會保持對象的生命,所以有時候為了回收記憶體,自己要將其設為nil,以便釋放記憶體,否則記憶體可能會被用光。
4. property的修飾符有一定變化。a)strong等同於retain;b)weak是弱指標,當對象釋放時會自動化佈建為nil;c)unsafe_unretained等同於assign只有iOS4才應該使用;d)copy和以前的copy一樣,複製一個對象並建立strong關聯;e)assign不能用於對象,應該用於BOOL、int和float等實值型別。
5. 如果dealloc方法只是釋放對象,則不需要此方法,但如果dealloc中處理了其它非記憶體資源釋放,如定時器、Core Foundation對象,則仍然需要在dealloc方法中進行手動釋放,但不能調用[super dealloc]。
6. 由於ARC只作用於Objective-C對象,有時候要用到Core Foundation對象,兩者之間的轉換可以使用toll-free bridging來很方便地完成,例如NSString和CFStringRef。編譯器必須知道由誰來負責釋放轉換後的對象,如果你把一個Objective-C對象當作Core Foundation對象來使用,ARC將不再負責釋放該對象,在兩種對象之間進行轉換時,要顯示地移交或者接受權利。
7. 函數參數和局部變數一樣,都是strong指標,這種對象在函數入口處會被retain,並且對象會持續存在直到指標被銷毀。
8.
1 - (NSString *)escape:(NSString *)text {2 return [(NSString *)CFURLCreateStringByAddingPercentEscapes(3 NULL,4 (CFStringRef)text, // 這裡需要進行bridging casts,將text臨時當作CFStringRef對象來使用。5 NULL,6 (CFStringRef)@"!*'();:@&=+$,/?%#[]", // 這裡不用bridging casts,因為這是常量,不需要釋放!7 CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding)) 8 autorelease];9 }
9. __bridge轉換不僅僅局限於Core Foundation對象,某些API使用void *指標作為參數,允許你傳遞任何東西的引用,比如Objective-C對象、Core Foundation對象或malloc()記憶體緩衝區等等。那麼傳參數的時候將這些對象轉換為void *,如:[UIView beginAnimations:nil context:(__bridge void *)someObject],在使用這些參數的地方再將其轉換回來,如:MyClass *myObject = (__bridge MyClass *)context。
10. 記憶體管理權的移交有三種情況,a)使用CFBridgingRelease()或__bridge_transfer將管理僅移交給Objective-C;b)使用CFBridgingRetain()或__bridge_retained將管理權移交給Core Foundation;c)使用__bridge來臨時使用某對象,不改變管理權。
11. 在ARC之前只有成員變數才會預設設為nil,在arc中局部對象指標會被設為nil,局部實值型別和實值型別指標還是隨機數。
12. 所有的Core Foundation物件類型都與Objective-C能夠toll-free bridged,但是UIColor不能,因為UIColor與CGColor並不是toll-free bridged,所以把CGColor放入NSArray要強制轉換為id類型。
13. property中的屬性名稱不能以new開頭,除非將getter指定指定為另外一個名字,@property NSString *newTitle;會出錯,@property (getter=theNewTitle) NSString *newTitle;正確。
14. autorelease pool變成了一種語言結構,而不是以前的類,@autoreleasepool{}比NSAutoreleasePool快六倍。在一個很大的迴圈中,有時候迴圈xx次進行一次NSAutoreleasePool清除工作,但其實這是不必要的,每迴圈一次清一次也無所謂,現在@autoreleasepool指令比NSAutoreleasePool快六倍,在迴圈中直接使用也不用擔心效能問題。
15. block會捕獲自己使用到的所有變數,如果用到成員變數,那麼成員變數所在的類會被retain,這樣這個類就不會被釋放,解決辦法是使用局部變數,NSString *text = self.artistName;,然後在block中使用text,而不是self.artistName,就不會出現問題。
16. 有時候block避免不了使用self對象,ARC以前可以建立一個局部的__block對象,把self值賦值過去,如:__block MyClass *blockSelf = self;,在block中引用這個__block局部變數來訪問self的屬性都不會retain self,但是在ARC中即使使用了__block來標記這個局部變數,它也是強引用的,這時__block的唯一功能是允許你修改已捕獲的變數。ARC的解決辦法是定義弱引用:__weak MyClass *weakSelf = self;,這樣weakSelf引用了self,但不進行retain,在block中捕獲weakSelf而不是self,因此不存在所有權迴環。在簡單應用中block屬於self,所以block不可能在self被釋放後還能被調用,有時候在block中檢查這個weakSelf被認為是不必要的,但是如果block被非同步呼叫,則建立強引用來保持對象存活就有必要了,因此在ARC中使用block,而且要避免捕獲self,可以這樣:
1 - (void)doSomething 2 { 3 __weak weakSelf = self; 4 block = ^() { 5 id strongSelf = weakSelf; 6 if ( strongSelf != nil ) { 7 // do stuff with strongSelf 8 } 9 };10 }
17. 如果建立一個對象,等待5秒後執行某一block,然後釋放掉該對象,在ARC以前應該這樣:
1 - (void)doSomething2 {3 MyClass *object = [[MyClass alloc] init];4 object.block = ^(void) {5 // do stuff6 [object autorelease];7 };8 [object launchAfter:5];9 }
在ARC中不允許使用autorelease,所以去掉釋放那一行,那麼這樣會導致block永遠不會被執行,因為object對象在此函數返回後被釋放。解決辦法是定義__block類型變數,這種類型是強引用,且block中能修改其值,然後在block中將些變數設為nil,如下:
1 - (void)doSomething2 {3 __block MyClass *object = [[MyClass alloc] init];4 object.block = ^(void) {5 // do stuff6 object = nil;7 };8 [object launchAfter:5];9 }
18.
1 - (void)doSomething2 {3 NSString *string;4 @autoreleasepool {5 string = [NSString stringWithFormat:…];6 }7 // the string object is still alive here8 }
19.
1 - (void)doSomething2 {3 __autoreleasing NSString *string;4 @autoreleasepool {5 string = [NSString stringWithFormat:…];6 }7 // the string object is still deallocated here8 NSLog(@"%@", string); // crash!9 }
20. 編寫自己的out-parameter方法:
1 - (NSString *)fetchKeyAndValue:(__autoreleasing NSNumber **)theValue 2 { 3 NSString *theKey; 4 NSNumber *theValue; 5 6 // do whatever you need to do here 7 8 *value = theValue; 9 return theKey;10 }
21. Core Foundation對象不能autorelease,autorelease完全純屬於Objective-C,有些人通過轉換Core Foundation對象為id,再調用autorelease,這在ARC中明顯不能工作,因為不能調用autorelease。