1.ARC空聲明變量
使用ARC的另一個優勢是所有未初始化的變量默認都是“空值化”的。這意味着像下面這樣的聲明使用ARC編譯后指向的是空值(nil):
NSObject *myObject1,*myObjects2;
不過要注意的是,與其他高級編程語言不同,ARC不會自動將標量的值設置為零。
這意味着以下幾行代碼聲明的變量其值並不等於零:
int a;
int b;
2.Objective-C命名約定
如果你在Person對象中寫了一個叫做newPersonName的方法,ARC會認為該方法返回一個分配過的對象。使用ARC(或者不適用ARC)編譯過的調用代碼和方法newPersonName運行時一切正常。但是如果這一方法所在的類沒有使用ARC編譯而調用方法使用了ARC編譯,程序就會奔潰。反過來,如果newPersonName方法是使用ARC編譯的而調用代碼沒有,就會出現內存泄露。
3.覆蓋默認行為
雖然從技術上說我們無法覆蓋LLVM的行為,但還是可以使用Clang源標注NS_RETURNS_RETAINED和NS_RETURNS_NOT_RETAINED來更改方法。newPersonName方法可以像下面這樣標注,以告訴ARC編譯器:盡管該方法名稱前面是new,返回的卻是未保留過的對象指針。
-(NSString *)newPersonName NS_RETURNS_NOT_RETAINED;
4.自由橋接
與Objective-C庫不同,我們在Objective-C中使用的標准C語言和Core Fundation類庫(CF *方法)不會遵循那些命名約定。這意味着ARC編譯器無法百分百地釋放不需要的內存。在ARC出現之前,我么可以將CF*對象強制轉變成NS*對象,這稱為自由橋接(toll-free bridging)。也就是說,我們可以將CFString*通過類型轉換變成NSString*類型。而有了ARC,我們便無法再這么做了,至少不指定一個所有權轉移修飾符時確實如此。
ARC允許使用一下這些所有權轉移修飾符:
__bridge
__bridge_retained
__bridge_transfer
1.__bridge
它告訴ARC不要增加它的引用計數的值,也不要更改所有權。
2.__bridge_retained
若想要轉換C指針類型並增加引用計數的值,我們可以使用第二個修飾符。當要從Objective-C方法(它創建一個Core Fundation對象並在之后使用CFRelease方法將其釋放)返回一個保留過的指針時,我們可以使用這個修飾符。如果Objective-C方法屬於NSRETURNS_RETAINDED系列,就要返回保留過的指針。
3.__bridge_transfer
如果要將Core Fundation指針類型轉換成Objective-C指針並為引用計數加1,可以使用最后一個修飾符。若Core Fundation方法創建一個對象,並且想要靠ARC來管理對象的內存,我們便可以使用這個修飾符。
5.忽略performSelector警告
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[uiViewController performSelector:finishMethod withObject:request];
#pragma clang diagnostic pop
6.block引起的循環保留
使用__block避免循環保留(無ARC)
__block id safeSelf = self;
self.myBlock = ^(NSString* returnedString){
safeSelf.labelControl.text = returnedString;
};
ARC會改變__block的語義,因此不應該使用它。在ARC中,__block引用會被保留而不是被復制,這意味着在ARC環境中前面的代碼仍然會引發循環保留。正確地方法是使用__weak或(__unsafe_unretained)引用,如:
使用__weak避免循環保留(有ARC)
__weak typeof(self) safeSelf = self;//IOS 5+
//__unsafe_unretained typeof(self) safeSelf = self;//IOS 4+
self.myBlock = ^(NSString* returnedString){
safeSelf.labelControl.text = returnedString;
};