設(shè)置ARC有效的編譯命令:
-fobjc-arc
Xcode 4.2 默認(rèn)設(shè)定為對(duì)所有的文件 ARC 有效
規(guī)則:
ARC有效情況下, 必須遵守的規(guī)則
不能使用 retain/release/retainCount/autorelease
不能使用 NSAllocateObject/NSDeallocateObject
須遵守內(nèi)存管理的方法命名規(guī)則
不要顯式調(diào)用 dealloc
使用 @autoreleasepool 塊替代 NSAutoreleasePool
不能使用區(qū)域 (NSZone)
對(duì)象型變量不能作為 C 語言結(jié)構(gòu)體 (struct/union) 的成員
顯式轉(zhuǎn)換 "id" 和 "void *"
對(duì)象型變量不能作為 C 語言結(jié)構(gòu)體 (struct/union) 的成員
雖然是 LLVM 編譯器 3.0, 但不論怎樣, C 語言的規(guī)約上沒有方法來管理結(jié)構(gòu)體成員的生存周期. 因?yàn)?ARC 把內(nèi)存管理的工作分配給編譯器, 所以編譯器必須能夠知道并管理對(duì)象的生存周期. 例如 C 語言的自動(dòng)變量 (局部變量) 可使用該變量的作用域管理對(duì)象. 但是對(duì)于 C 語言的結(jié)構(gòu)體成員來說, 這在標(biāo)準(zhǔn)上就是不可實(shí)現(xiàn)的.
要把對(duì)象型變量加入到結(jié)構(gòu)體成員中時(shí), 可強(qiáng)制轉(zhuǎn)換為 void * 或是附加前面所述的 __unsafe_unretained 修飾符 (__unsafe_unretained 修飾符的變量不屬于編譯器的內(nèi)存管理對(duì)象)
顯式轉(zhuǎn)換 id 和 void *
ARC 無效
id 變量強(qiáng)制轉(zhuǎn)換 void * 變量并不會(huì)出問題
id obj = [[NSObject alloc] init];
void *p = obj;
更進(jìn)一步, 將該 void * 變量賦值給 id 變量中, 調(diào)用其實(shí)例方法, 運(yùn)行時(shí)也不會(huì)有問題.
id o = p;
[o release];
ARC 有效
id 型或?qū)ο笮妥兞抠x值給 void * 或者逆向賦值時(shí)都需要進(jìn)行特定的轉(zhuǎn)換. 如果只想單純地賦值, 則可以使用 "__bridge 轉(zhuǎn)換".
id obj = [NSObject alloc] init];
void *p = (__bridge void *)obj;
id o = (__bridge id)p;
像這樣, 通過 "__bridge 轉(zhuǎn)換", id 和 void * 就能夠相互轉(zhuǎn)換.
但是轉(zhuǎn)換為 void * 的 __bridge 轉(zhuǎn)換, 其安全性與賦值給 __unsafe_unretained 修飾符相近, 甚至?xí)?/b>. 如果管理時(shí)不注意賦值對(duì)象的所有者, 就會(huì)因懸垂指針而導(dǎo)致程序崩潰.
__bridge 轉(zhuǎn)換中還有另外兩種轉(zhuǎn)換, 分別是 "__bridge_retained 轉(zhuǎn)換" 和 "__bridge_transfer 轉(zhuǎn)換"
id obj = [[NSObject alloc] init];
void *p = (__bridge_retained void *)obj;
__bridge_retained 轉(zhuǎn)換可使要轉(zhuǎn)換賦值的變量也持有所賦值的對(duì)象.?
ARC 無效
id obj = [[NSObject alloc] init];
void *p = obj;
[(id)p retain];__bridge_retained 轉(zhuǎn)換變?yōu)榱?retain.?
__bridge_transfer 轉(zhuǎn)換提供與此相反的動(dòng)作, 被轉(zhuǎn)換的變量所持有的對(duì)象在該變量被賦值給轉(zhuǎn)換目標(biāo)變量后隨之釋放
id obj = (__bridge_transfer id)p;
ARC 無效時(shí) =>
id obj = (id)p;
[obj retain];
[(id)p release];
__bridge_retained 轉(zhuǎn)換與 retain 類似, __bridge_transfer 轉(zhuǎn)換與 release 相似. 在給 id obj 賦值時(shí) retain 即相當(dāng)于 __strong 修飾符的變量
如果使用以上兩種轉(zhuǎn)換, 那么不使用 id 型或?qū)ο笮妥兞恳部梢陨?持有以及釋放對(duì)象. 雖然可以這樣做, 但在 ARC 中并不推薦這種方法.?void *p = (__bridge_retained void *)[[NSObject alloc] init];
NSLog(@"class=%@", [(__bridge id)p class]);
(void)(__bridge_transfer id)p;該源代碼與 ARC 無效時(shí)的下列源代碼相同
ARC 無效
id p = [NSObject alloc] init];
NSLog(@"class=%@", [p class]);
[p release];這些轉(zhuǎn)換多數(shù)使用在 Objective-C 對(duì)象與 Core Foundation 對(duì)象之間的相互變換中