2011年6月25日 星期六

初探ARC - Automatic Reference Counting

WWDC 2011的影片開始下載
今天颱風天
那就抓個大家之前有討論的ARC來研究一下
下面是我的小小心得 :D

我想寫過iOS的人
絕對最痛很的就是令人髮指的Memory Management
就連TBBT的leonard也為此煩惱

source:
http://digdog.tumblr.com/post/3628378498/actually-sheldon-has-better-design-if-youre

程式中充斥著retain, release, autorelease
相信即使是老手,也難免會恍神而不小心少release而產生memory leakage
或是多release而產生bad access直接當掉
在這個大家都用garbage collection的時代
這種memory management的方式實在讓人寫得很痛苦

當然目前objective-c的做法也不能說完全沒有好處
畢竟gc的動作是無法預測什麼時候會去執行的
也許剛好在你正在忙的時候給你gc一下就卡了
這也是為什麼iOS跑起來可以比別家順的其中一個原因。
而在iOS5首次提出了ARC(Automatic Reference Counting)這個解決方案
試圖讓開發者減少寫Reference Counting的時候產生的錯誤。

ARC有哪些重點?
1. 它是Compile-time的技術,並不是runtime有一個thread去幫你處理reference count..
2. 開發者不能再直接使用retain, release, autorelease,改由compiler幫你塞這些code
3. 所有的property不再使用retain, assign而改用strong, weak取代
4. NSAutoreleasePool也要改用特有的 @autoreleasepool{ } 來取代
沒了!!

好啦,其實當然不只這樣,但是先從簡單的來
先看下面的code

-(NSString*)helloString
{
return [[NSString alloc] initWithFormat:@"Hello %@", _name];
}

以現在的MRC(Manual Reference Counting)環境
這種寫法有潛在的memory leak的風險
因為根據命名規則,非new, copy, mutableCopy開頭的message回傳的物件不能是retained object
而是要retained and autoreleased object
所以可能要改成這樣的寫法

-(NSString*)helloString
{
return [NSString stringWithFormat:@"Hello %@", _name];
}

但是如果使用了ARC之後
前後兩個方法都可以
主要是因為compiler會分析你的程式碼中呼叫的message是否有含alloc, new, copy, mutableCopy這些開頭
如果有的話就知道回傳的object的ownership是你的
接著根據你所在的message是否有alloc, new,... 來決定你回傳的物件是哪種類型。
以上面message為例子,回傳的應該是一個retained and autoreleased object
以往MRC中,我們就要跟leonard一樣,好好的計算一下才不會錯
但是在ARC這些複雜的加減法都交給compiler來幫我們搞定,完全不需要知道實作細節。

另外memory mangagement還有一個重點是在member variable
以前我們定義在class中的member variable並沒有留下是否要retain物件的資訊
除非我們透過@property (retain)或是@property (assign)的方法才可以知道個別的ownership語意。
但是在ARC中,因為所有retain/release都是要自動的
因此所有的Member variable就定義為預設都是strong type,這有點類似@property (retain)的味道
除非我們在member variable前加上__weak這個描述才會是weak type,這就有點類似@property (assign)
所以在程式碼中,若物件被指到strong pointer,就會自動retain
weak pointer則不會retain..

另外weak reference還有一個非常吸引我的功能
就是所謂的zeroing weak reference.
這個不得不歡呼一下
以前我們在用delegate pattern的時候
文件都教我們使用@property (assign)來hold delegate object
目的就是為了避免circular reference所造成的memory leakage
但是常常會遇到delegate所指到的object已經因為retain count歸零而被清掉了
若我們還去使用它 系統馬上就當給你看
所以以前我們都必須要記得把delegate設成nil
在ARC當中,如果weak pointer所指到的object的retain count已經是0的時候
則這個weak pointer也會被設成0
這就是所謂的"zeroing weak reference"
所以在weak pointer中又比以前的@property (assign)更為安全

從我最新抓的xcode4.2 with iOS5的環境來看
預設已經是把ARC變成預設了
而舊的project可以透過refactor的方式Convert to Objective-C ARC
究竟麻不麻煩,這我還不敢發表評論 XD
但是我相信長痛不如短痛
ARC絕對是對objective-c的記憶體管理有非常大的幫助。
讓我們準備擁抱ios5的ARC時代吧

References
[1] http://clang.llvm.org/docs/AutomaticReferenceCounting.html

沒有留言:

張貼留言