Xcode ARC詳解全攻略
手動管理內存經常忘掉release或autorelease,或者因為release多了、retain少了導致空指針引用程序崩潰,還要經常按COMMAND+SHIFT+B,豈止頭疼,簡直蛋疼有木有。
雖然objective-c 2.0支持垃圾收集器(Garbage Collection,簡稱GC),但是垃圾收集器只能在MAC程序上開啟,ios上沒辦法用。就算在MAC應用程序上可以用,GC也會有性能上的損耗。
現在LLVM3.0多了一個給力的新東西,叫Automatic Reference Counting。開啟這個選項之后,LLVM會在編譯階段自動幫開發者完成“手動”的內存管理。同時,所有代碼中的retain,release和 autorelease會被標記成錯誤,也就是說,我們完全不需要用以前頭蛋俱疼的方式管理內存了。
ARC不僅可以修復錯誤,還能增強性能。根據WWDC 2011大會的介紹,retain/release快了2.5倍,@autoreleasepool快了6倍,objc_msgSend快了33%。
一、舊工程開啟ARC的方法
xCode4.2中已經自帶了LLVM3.0,在用新的模板建立工程時,編譯器默認選擇LLVM3.0,并且開啟ARC。如圖。
xCode4.2 也為ARC提供了自動轉換工具。首先將工程的編譯器切換為LLVM3.0,然后在菜單里選擇Edit—-Refactor—-Convert to Objective-C ARC…。LLVM會將不能轉換的部分標記為錯誤,要求我們手動修改。一般NSAutoReleasePool不能自動轉換,要手動轉為 @autoreleasepool。CF框架的方法也不能自動轉換,而release、retain和autorelease是可以自動轉換的。我們將不 能自動轉換的錯誤手動修改好后,編輯器將完成自動轉換。
對 于可能出現的錯誤,WWDC 2011的視頻中給出了一些例子。比如用static count來處理singletons pattern;用weak來申明delegate pattern;用dispatch_once來保證多線程的安全;在case關鍵字后面加上大括號{..}來限制case里面申明變量的作用范圍等等。
二、開啟ARC后需要遵循的原則
1、不能調用retain/release/autorelease,這些由編譯器來完成。
2、結構內不能有對象指針,如果結構中包含,則需要以類代替結構。
3、不能使用id<–>void *的類型轉換,因為編譯器不知道這個void *是否需要retained。
4、不能使用NSAutoreleasedPool,要用@autoreleasepool {……}來代替。
三、ARC中引入的四個新的關鍵字
1、Strong Reference,強引用。默認類型,不加任何關鍵字(也可以寫成__strong)。相當于之前代碼中的retain屬性。
2、Autoreleasing Reference,自動釋放引用。通常出現在例如系統error處理函數中(關鍵字__autoreleasing),描述out-parameters用,只保存在棧中,不太常用。
3、Unsafe Reference,不安全引用。類似于之前代碼中的assign屬性,不分配內存(關鍵字__unsafe_unretained),相當于起了個別名。
4、Weak Reference,弱引用。前面提到過,不增加計數,當對象開始釋放時,立刻設置成nil。
四、ARC中循環引用造成內存泄露的原因與解決辦法
ARC通過記錄指向某對象的指針數量來判斷該對象是否應該被釋放(0代表可以釋放)。因而如果出現循環引用,就會出現內存泄露。如下圖所示。
五、Instruments的Leaks的新功能
一篇深入討論 ARC的文章
http://longweekendmobile.com/2011/09/07/objc-automatic-reference-counting-in-xcode-explained/