ARC是iOS 5推出的新功能,全稱叫 ARC(Automatic Reference Counting)。簡單地說,就是代碼中自動加入了retain/release,原先須要手動添加的用來處理內存管理的引用計數的代碼能夠自動地由編譯器完成了。 工具
該機能在 iOS 5/ Mac OS X 10.7 開始導入,利用 Xcode4.2 可使用該機能。簡單地理解ARC,就是經過指定的語法,讓編譯器(LLVM 3.0)在編譯代碼時,自動生成實例的引用計數管理部分代碼。有一點,ARC並非GC,它只是一種代碼靜態分析(Static Analyzer)工具。 學習
經過一小段代碼,咱們看看使用ARC先後的變化點。 spa
@interface NonARCObject : NSObject { NSString *name; } -(id)initWithName:(NSString *)name; @end @implementation NonARCObject -(id)initWithName:(NSString *)newName { self = [super init]; if (self) { name = [newName retain]; } return self; } -(void)dealloc { [name release]; [Super dealloc]; } @end
@interface ARCObject : NSObject { NSString *name; } -(id)initWithName:(NSString *)name; @end @implementation ARCObject -(id)initWithName:(NSString *)newName { self = [super init]; if (self) { name = newName; } return self; } @end咱們以前使用Objective-C中內存管理規則時,每每採用下面的準則
而使用ARC後,咱們能夠不須要這樣作了,甚至連最基礎的release都不須要了。 指針
使用ARC有什麼好處呢? code
關於第二點,因爲 XCode4.2 中缺省ARC就是 ON 的狀態,因此編譯舊代碼的時候每每有」Automatic Reference Counting Issue」的錯誤信息。 orm
這個時候,能夠將項目編譯設置中的「Objectice-C Auto Reference Counteting」設爲NO。以下所示。 對象
若是隻想對某個.m文件不適應ARC,能夠只針對該類文件加上 -fno-objc-arc 編譯FLAGS,以下圖。 生命週期
因爲ARC並非GC,並須要一些規則讓編譯器支持代碼插入,因此必須清楚清楚了這些規則後,才能寫出健壯的代碼。 內存
ObjectiveC中的對象,有強參照(Strong reference)和弱參照(Weak reference)之分,當須要保持其餘對象的時候,須要retain以確保對象引用計數加1。對象的持有者(owner)只要存在,那麼該對象的強參照就一直存在。
對象處理的基本規則是firstName做爲」natsu」字符串對象的最初持有者,是該NSString類型對象的Strong reference。
(s2)這裏將firstName代入到aName中,即aName也成爲了@」natsu」字符串對象的持有者,對於該對象,aName也是Strong reference。
(s3)這裏,改變firstName的內容。生成新的字符串對象」maki」。這時候firstName成爲」maki」的持有者,而@」natsu」的持有者只有aName。每一個字符串對象都有各自的持有者,因此它們都在內存中都存在。
(s4)追加新的變量otherName, 它將成爲@」maki」對象的另外一個持有者。即NSString類型對象的Strong reference。
(s5)將otherName代入到aName,這時,aName將成爲@」maki」字符串對象的持有者。而對象@」natsu」已經沒有持有者了,該對象將被破棄。
接下來咱們來看看弱參照 (Weak reference) 的使用方式。
(w1)與強參照方式一樣,firstName做爲字符串對象@」natsu」的持有者存在。便是該NSString類型對象的Strong reference。
(w2)使用關鍵字__weak,聲明弱參照weakName變量,將firstName代入。這時weakName雖然參照@」natsu」,但還是Weak reference。即weakName雖然能看到@」natsu」,但不是其持有者。
(w3)firstName指向了新的對象@」maki」,成爲其持有者,而對象@」natsu」由於沒有了持有者,即被破棄。同時weakName變量將被自動代入nil。
ARC中關於對象的引用參照,主要有下面幾關鍵字。使用strong, weak, autoreleasing限定的變量會被隱式初始化爲nil。
__strong變量聲明缺省都帶有__strong關鍵字,若是變量什麼關鍵字都不寫,那麼缺省就是強參照。
__weak上面已經看到了,這是弱參照的關鍵字。該概念是新特性,從 iOS 5/ Mac OS X 10.7 開始導入。因爲該類型不影響對象的生命週期,因此若是對象以前就沒有持有者,那麼會出現剛建立就被破棄的問題,好比下面的代碼。
NSString __weak *string = [[NSString alloc] initWithFormat:@"First Name: %@", [self firstName]]; NSLog(@"string: %@", string); //此時 string爲空
若是編譯設定OS版本 Deployment Target 設定爲這比這低的版本,那麼編譯時將報錯(The current deployment target does not support automated __weak references),這個時候,咱們可使用下面的__unsafe_unretained。
弱參照還有一個特徵,即當參數對象失去全部者以後,變量會被自動付上nil (Zeroing)。
__unsafe_unretained該關鍵字與__weak同樣,也是弱參照,與__weak的區別只是是否執行nil賦值(Zeroing)。可是這樣,須要注意變量所指的對象已經被破棄了,地址還還存在,但內存中對象已經沒有了。若是仍是訪問該對象,將引發「BAD_ACCESS」錯誤。
__autoreleasing該關鍵字使對像延遲釋放。好比你想傳一個未初始化的對像引用到一個方法當中,在此方法中實例化此對像,那麼這種狀況可使用__autoreleasing。他被常常用於函數有值參數返回時的處理,好比下面的例子。
- (void) generateErrorInVariable:(__autoreleasing NSError **)paramError { .... *paramError = [[NSError alloc] initWithDomain:@"MyApp" code:1 userInfo:errorDictionary]; } .... { NSError *error = nil; [self generateErrorInVariable:&error]; NSLog(@"Error = %@", error); }
又如函數的返回值是在函數中申請的,那麼但願釋放是在調用端時,每每有下面的代碼。
-(NSString *)stringTest { NSString *retStr = [NSString stringWithString:@"test"]; return [[retStr retain] autorelease]; } // 使用ARC -(NSString *)stringTest { __autoreleasing NSString *retStr = [NSString alloc] initWithString:@"test"]; return retStr; }
即當方法的參數是id*,且但願方法返回時對象被autoreleased,那麼使用該關鍵字。
從此,咱們將更加深刻ARC,學習其更多的特性。