ARC 簡述

  • 簡介        

       ARC是編譯器特性,而不是iOS運行時特性(除了weak指針系統)【ARC和手動內存管理性能是一樣的,有些時候還能更加快速,因爲編譯器還可以執行某些優化】

  • 指針保持對象的生命

       ARC的規則非常簡單:只要還有一個變量指向對象,對象就會保持在內存中。(當指針指向新值,或者指針不再存在時,相關聯的對象就會自動釋放)

       我們可以按“所有權”(ownership)來考慮ARC對象,一個對象可以有多個擁有者。只有當對象一個擁有者也沒有的情況下才被釋放。而能夠作爲對象擁有者的指針爲“strong”,默認的實例變量和本地變量都是strong類型的指針。

       另外還有一種“weak”指針,weak變量仍然指向一個對象,但不是對象的擁有者;當weak指向的變量的擁有者不再擁有時,變量被釋放,此時weak變量會自動變爲nil,稱爲“zeroing weak pointer”,這樣阻止了weak指針繼續指向已釋放的對象。

       weak指針主要用於“父-子”關係,父親擁有一個兒子的strong指針,因此是兒子的所有者;但爲了阻止所有權迴環,兒子需要使用weak指針指向父親,典型例子是delegate模式

id obj = [array objectAtIndex:0];
[array removeObjectAtIndex:0];
NSLog(@"%@",obj);

在ARC中這段代碼是完全合法的。

  • ARC的限制

       ARC只能工作與Objective-C對象,如果應用使用了Core Foundation 或malloc()/free(),此時需要你來管理內存。因爲strong指針會保持對象的生命,某些情況下你仍然需要手動設置這些指針爲nil,無論你何時創建了一個新對象時,都需要考慮誰擁有該對象,以及這個對象需要存活多久。

  • XCode 的ARC遷移

    ARC是LLVM3.0編譯器的特性,而現有工程可能使用老的GCC4.2或LLVM-GCC編譯器,因此需要首先設置使用LLVM3.0編譯器

    Project Settings -> target -> Build Settings 搜索compiler,同樣,Build Options 下面的Run Static Analyzer選項也最好啓用,這樣每次Xcode編譯項目時,都會運行靜態代碼分析工具來檢查我們的代碼(Xcode的ARC 自動轉換可上網搜索方法,在這裏不做闡述)

    -fno-obj-arc 可以禁止某些文件的ARC

  • 屬性 property

       對於.h 頭文件,Xcode主要是將屬性定義由retain變爲strong,這些屬性是類對外的接口,因此定義在.h文件中

       在ARC之前,開發者經常會在.m實現文件中使用class extension 來定義 private property,這樣做主要是簡化實例對象的手動內存管理,讓property的setter方法自動管理原來對象的釋放,以及新對象的retain,但是有了ARC,這樣的代碼就不再需要了,一般來說,僅僅爲了簡化內存管理,是不再需要使用property的,只有那些屬於public接口的實例變量,才應該定義爲property。

       我們可以直接在.m類實現中定義private實例變量

NSMutableString *currentStringValue;
NSMutableArray *searchResults;
SoundEffect *soundEffect;

       我們在使用時,雖然沒有定義property,也可以直接 [self.soundEffect play],也可以[[self soundEffect] play]    

       作爲property的最佳實踐,如果你定義了某個東西爲property,則你應該在任何地方都按屬性來使用它。

       在ARC中,所有*outlet*屬性都推薦使用weak,這些view對象已經屬於View Controller 的view hierarchy ,不需要再次定義爲strong,唯一使用strong的outlet是File’s Owner,連接到nib的頂層對象

       將outlet 定義爲weak的優點是簡化了viewDidUnload方法的實現。只要你保持一個對象的指針,對象就會存活,當你不需要某個對象時,可以手動設置指針爲nil。

       property的修飾符總結:

           strong:等同於“reatain”屬性稱爲對象的擁有者

           weak:屬性是weak pointer ,當對象釋放時會自動設置爲nil,記住Outlet應該使用Weak

           unsafe_unretained:等同於之前的“assign”只有iOS4才應該使用

           copy:和之前的copy一樣,複製一個對象並創建strong關聯

           assign:對象不能使用assign,但原始類型(BOOL,int,float)仍然可以使用

ReadOnly property

       在ARC之前,我們可以如下定義一個readonly property:@property(nonatomic,readonly)NSString *result;這回隱式創建一個assign property,這種用法對於readonly值來說是適當的,畢竟你何必對只讀數據進行retain那,但在ARC中會報錯;你必須顯式使用strong,weak或unsafe_unretained,多數情況下使用strong是正確的

       @property(nonatomic, strong, readonly) NSString *result;

對於readonly property,我們應該總是使用self.propertyName來訪問實例變量(除了init和自定義的getter和setter方法),否則直接修改實例變量會混淆ARC並導致奇怪的Bug,正確的方法是使用class extension 重新定義 property爲readwrite;

   .h文件:@property (nonatomic, strong, readonly) NSNumber *temperature;

   .m 文件:@property(nonatomic, strong, readwrite) NSNumber *temperature;


   



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章