OC高級編程iOS內(nèi)存管理-第1章-自動引用計數(shù)

自動引用計數(shù)


  • 什么是自動引用計數(shù)
  • 內(nèi)存管理/引用計數(shù)
  • ARC規(guī)則
  • ARC的實現(xiàn)

1.1 什么是自動引用計數(shù)

  • ARC和MRC的區(qū)別:
    MRC:(Manual Reference Counting)也就是非ARC崩溪,在Xcode4之前伶唯,Object_C的內(nèi)存管理就需要開發(fā)人員手動維護乳幸。
    ARC:(Automatic Reference Counting)也就是ARC粹断,翻譯成中文就是:【自動引用計數(shù)】瓶埋,不需要開發(fā)人員手動維護养筒,系統(tǒng)會在合適的時候調(diào)用內(nèi)存管理方法晕粪。

顧名思義巫湘,自動引用計數(shù)(ARC尚氛,Automatic Reference Counting)是指內(nèi)存管理中對引用采取自動計數(shù)的技術(shù)阅嘶。以下摘自蘋果的官方說明奈懒。
在Objective-C中采用Automatic Reference Counting(ARC)機制磷杏,讓編輯器來進行內(nèi)存管理极祸。在新一代的Apple LLVM編輯器中設(shè)置ARC為有效狀態(tài)遥金,就無需再次鍵入retain或release代碼稿械,這在降低程序崩潰美莫、內(nèi)存泄漏等風險的同時厢呵,很大程度上減少了開發(fā)程序的工作量襟铭。編譯器完全清楚目標對象寒砖,并能立刻釋放那些不再被使用的對象入撒。如此一來茅逮,應(yīng)用程序?qū)⒕哂锌深A(yù)測性献雅,且能流程運行挺身,速度也將大幅提升章钾。

1.2 內(nèi)存管理/引用計數(shù)

可以用開關(guān)房間的燈為例來說明引用計數(shù)的機制贱傀。
加入辦公室里的照明設(shè)備只有一個府寒。上班進入辦公室的人需要照明株搔,所以要開燈纵隔,下班離開辦公室的人不需要照明巨朦,所以要把燈關(guān)掉糊啡。若是很多人上下班棚蓄,每個人都開燈或者關(guān)燈梭依,那么辦公室的情況又將如何呢役拴?最早下班離開的人如果關(guān)了燈河闰,那辦公室還沒走的所有人都將處于一片黑暗之中姜性。
解決這一問題的辦法是使辦公室在還有至少1人的情況下保持開燈狀態(tài)部念,而在無人時保持關(guān)燈狀態(tài)妓湘。

(1)最早進入辦公室的人開燈榜贴。
(2)之后進入辦公室的人,需要照明秆麸。
(3)下班離開辦公室的人沮趣,不需要照明房铭。
(4)最后離開辦公室的人關(guān)燈(此時已無人需要照明)缸匪。

為判斷是否還有人在辦公室,這里導入計數(shù)功能來計算“需要照明的人數(shù)”砂心。下面讓我們看看這一功能如何運作的辩诞。

(1)第一個人進入辦公室译暂,“需要照明的人數(shù)”加1秧秉。計數(shù)值從0變成了1荧嵌,因此要開燈啦撮。
(2)之后每當有人進入辦公室赃春,“需要照明的人數(shù)”就加1.如計數(shù)值從1變成2。
(3)每當有人下班離開辦公室狭吼,“需要照明的人數(shù)”就減1刁笙。如計數(shù)值從2變成1疲吸。
(4)最后一個人下班離開辦公室時,“需要照明的人數(shù)”減1烦租。計數(shù)值從1變成了0叉橱,因此要關(guān)燈窃祝。

如下圖:
引用計數(shù)圖1.png

在Objective-C中大磺,“對象”相當于辦公室的照明設(shè)備杠愧。“對象的使用環(huán)境”相當于上班進入辦公室的人绳瘟。上班進入辦公室的人對辦公室照明設(shè)備發(fā)出的動作糖声,與Objective-C中的對應(yīng)關(guān)系如表1-1所示分瘦。

表1-1 對辦公室照明設(shè)備所做的動作和對Objective-C的對象所做的動作
對照明設(shè)備所做的動作 對Objective-C對象所做的動作
開燈 生成對象
需要照明 持有對象
不需要照明 釋放對象
關(guān)燈 廢棄對象

如圖:
引用計數(shù)圖2.png

內(nèi)存管理的思考方式

首先來學習引用計數(shù)式內(nèi)存管理的思考方式蘸泻。看到“引用計數(shù)”這個名稱嘲玫,我們便會不自覺的聯(lián)想到“某處有某物多少多少”而將注意力放到計數(shù)上悦施。但其實,更加客觀趁冈、正確的思考方式是:

  • 自己生成的對象拜马,自己持有渗勘。
  • 非自己生成的對象,自己也能持有俩莽。
  • 不再需要自己持有的對象時釋放旺坠。
  • 非自己持有的對象無法釋放。
    上文出現(xiàn)了“生成”扮超、“持有”取刃、“釋放”三個詞。而在Objective-C內(nèi)存管理中還要加上“廢棄”一詞出刷,各個詞表示的Objective-C方法如表1-2璧疗。
表1-2 對象操作與Objective-C方法的對應(yīng)
對照明設(shè)備所做的動作 對Objective-C對象所做的動作 Object-C方法
開燈 生成對象 alloc/new/copy/mutableCopy等方法
需要照明 持有對象 retain方法
不需要照明 釋放對象 release方法
關(guān)燈 廢棄對象 dealloc方法

自己生成的對象,自己持有

使用以下名稱開頭的方法名意味著自己生成的對象只有自己持有:

  • alloc
  • new
  • copy
  • mutableCopy
/*
* 自己生成并持有對象
*/
id obj = [[NSObject alloc] init];
/*
* 自己持有對象
*/

copy方法利用基于NSCopying方法約定馁龟,由各類實現(xiàn)的copyWithZone:方法生成并持有對象的副本崩侠。與copy方法類型,mutableCopy方法利用基于NSMutableCopying方法約定坷檩,由各類實現(xiàn)的mutableCopyWithZone:方法生成并持有對象的副本却音。兩者的區(qū)別在于改抡,copy方法生成不可變更的對象,而mutableCopy方法生成可變更的對象系瓢。

非自己生成的對象阿纤,自己也能持有

/*
* 取得非自己生成的對象
*/
id obj = [[NSMutableArray array];
/*
* 取得的對象存在,但自己不持有對象
*/

[obj retain];
/*
* 自己持有對象
*/

通過retain方法夷陋,非自己生成的對象跟用alloc/new/copy/mutableCopy方法生成并持有的對象一樣欠拾,成為了自己所持有的。

不再需要自己持有的對象時釋放

/*
* 取得非自己生成的對象
*/
id obj = [[NSMutableArray array];
/*
* 取得的對象存在肌稻,但自己不持有對象
*/

[obj release];
/*
* 釋放對象
* 對象一經(jīng)釋放絕對不可訪問清蚀。
*/

無法釋放非自己持有的對象

/*
* 取得非自己生成的對象
*/
id obj = [[NSMutableArray array];
/*
* 取得的對象存在,但自己不持有對象
*/

[obj release];
/*
* 對象已釋放
*/

[obj release];
/*
* 釋放之后再次釋放已非自己持有的對象爹谭!應(yīng)用程序崩潰枷邪!
* 崩潰情況:
* 再度廢棄一經(jīng)廢棄了的對象時崩潰,訪問一經(jīng)廢棄的對象時崩潰诺凡。 
*/

或者在“取得的對象存在东揣,但自己不持有對象”時釋放,也會造成程序崩潰腹泌。
以上四項內(nèi)容嘶卧,就是“引用計數(shù)式內(nèi)存管理”的思考方式。

關(guān)于引用計數(shù)器:

每個OC對象都有自己的引用計數(shù)器凉袱,是一個整數(shù)表示對象被引用的次數(shù)芥吟,即現(xiàn)在有多少東西在使這個對象。對象剛被創(chuàng)建時专甩,默認計數(shù)器值為1钟鸵,當計數(shù)器的值變?yōu)?時,則對象銷毀涤躲。
在每個OC對象內(nèi)部棺耍,都專門有4個字節(jié)的存儲空間來存儲引用計數(shù)器。

引計數(shù)器的作用

判斷對象要不要回收的唯一依據(jù)就是計數(shù)器是否為0种樱,若不為0則存在蒙袍。
操作:
當一個對象的引用計數(shù)器為0時,那么它將被銷毀嫩挤,其占用的內(nèi)存被系統(tǒng)回收害幅。一旦對象被回收了,那么他所占據(jù)的存儲空間就不再可用岂昭,堅持使用會導致程序崩潰(野指針錯誤)以现。

#pragma mark    -------------C語言里面malloc 用法-------------------

char *p = (char *)malloc(100);//C語言的動態(tài)分配  手動申請了100個字節(jié)的存儲空間
strcpy(p, "niming");//將字符串存儲到 指針變量p指向的內(nèi)存空間 
puts(p);//輸出
free(p);//釋放

#pragma mark    ------------- OC內(nèi)存管理 release 實例----------------
/*
 * 自己生成并持有對象
 */
 id obj = [[NSObject alloc] init];
 // 或
 id obj = [NSObject new];
/*
 * 釋放對象
 * 對象不可再被訪問
 */
  [obj release];
內(nèi)存管理基本原則(黃金法則)

1.如果你通過alloc,new,copy等開頭的方法,來創(chuàng)建了一個對象,那么你就必須調(diào)用release或者autorelease方法
2.誰創(chuàng)建叼风,誰release (個人顧個人原則)
3.誰retain取董,誰release(只要你調(diào)用了retain,無論這個對象是如何生成的无宿,你都要調(diào)用release)
總結(jié):有始有終茵汰,有加就應(yīng)該有減,曾經(jīng)讓某個對象計數(shù)器+1孽鸡,就應(yīng)該讓其在最后-1

dealloc(對象的銷毀)
/*
*(1)一定要[super dealloc]蹂午, 且要放到最后
*(2)對self(當前)所擁有的的其他對象做一次release操作
*/
 - (void)dealloc {
  [obj release];
  [super dealloc];
 }

當一個對象的引用計數(shù)器為0時,那么它將被銷毀彬碱,其占用的內(nèi)存被系統(tǒng)回收豆胸。當對象被銷毀時,系統(tǒng)會自動向?qū)ο蟀l(fā)送一條dealloc消息巷疼,一般會重寫dealloc方法晚胡,在這里釋放相關(guān)的資源,dealloc就像是對象的“臨終遺言”嚼沿。一旦重寫了dealloc方法就必須調(diào)用[super dealloc]估盘,并且放在代碼塊的最后調(diào)用(不能直接調(diào)用dealloc方法)。

給對象發(fā)送消息骡尽,進行相應(yīng)的計數(shù)器操作遣妥。
retain消息:使計數(shù)器+1,該方法返回對象本身
release消息:使計數(shù)器-1(并不代表釋放對象)
retainCount消息:獲得對象當前的引用計數(shù)器值

autorelease

說到Objective-C內(nèi)存管理攀细,就不能不提autorelease箫踩。
顧名思義,autorelease就是自動釋放谭贪。這看上去很像ARC境钟,但實際上它更類似于C語言中自動變量(局部變量)的特性。
我們來復習一下C語言的自動變量故河。程序執(zhí)行時吱韭,若某自動變量超出其作用域吆豹,該自動變量將被自動廢棄鱼的。
autorelease會像C語言的自動變量那樣對待對象實例。當超出其作用域(相當于變量作用域)時痘煤,對象實例的release實例方法被調(diào)用凑阶。另外,同C語言的自動變量不同的是衷快,編程人員可以設(shè)定變量的作用域宙橱。

#pragma mark -- ios 5.0之前的創(chuàng)建方式
    
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    id obj = [[NSObject alloc] init];
    [obj autorelease];
    [pool darin];// 此處等同于 “[obj release]”

#pragma mark -- 5.0之后

    @autoreleasepool {//代表開始創(chuàng)建自動釋放池
        
        // insert code here...
        NSLog(@"Hello, World!");
        
        Person *person = [[Person alloc] init];
        
        [person autorelease];
        
    }//結(jié)束自動釋放池

1.系統(tǒng)自帶的方法中,如果不包含 alloc new copy等關(guān)鍵字,則這些方法返回的對象 都是 autorelease
如: [NSDate date];
如 :

id array = [NSMutableArray arrayWithCapacity:1];

此源代碼等同于以下源代碼师郑。

id array = [[[NSMutableArray alloc] initWithCapacity:1] autorelease];

1.3 ARC規(guī)則

“引用計數(shù)式內(nèi)存管理”本質(zhì)在ARC中并沒有變化环葵,ARC只是自動地幫助我們處理“引用計數(shù)”的相關(guān)部分。在編譯單位上宝冕,可設(shè)置ARC有效或無效张遭。指定編譯器屬性為“-fobjc-arc”。

與Java的對比

在java中地梨,內(nèi)存管理由JVM完全負責菊卷,java中的“垃圾回收器”負責自動回收無用對象占據(jù)的內(nèi)存資源,這樣可以大大減少程序猿在內(nèi)存管理上花費的時間宝剖,可以更集中于業(yè)務(wù)邏輯和具體功能實現(xiàn)洁闰;但這并不是說java有了垃圾回收器程序猿就可以高枕無憂,將內(nèi)存管理拋之腦外了万细!一方面扑眉,實際上java中還存在垃圾回收器沒法回收以某種“特殊方式”分配的內(nèi)存的情況;另一方面赖钞,java的垃圾回收是不能保證一定發(fā)生的襟雷,除非JVM面臨內(nèi)存耗盡的情況。所以java中部分對象內(nèi)存還是需要程序猿手動進行釋放仁烹,合理地對部分對象進行管理可以減少內(nèi)存占用與資源消耗耸弄。

java的對象內(nèi)存狀態(tài)&&引用形式及回收時機,如下圖:
對象狀態(tài)轉(zhuǎn)換圖.png
  • 如何判斷java對象需要被回收卓缰?GC判斷方法

    • 引用計數(shù)计呈,引用計數(shù)法記錄著每一個對象被其它對象所持有的引用數(shù),被引用一次就加一征唬,引用失效就減一捌显;引用計數(shù)器為0則說明該對象不再可用;當一個對象被回收后总寒,被該對象所引用的其它對象的引用計數(shù)都應(yīng)該相應(yīng)減少扶歪,它很難解決對象之間的相互循環(huán)引用問題循環(huán)引用實例
    • 可達性分析算法:從GC Root對象向下搜索其所走過的路徑稱為引用鏈,當一個對象不再被任何的GC root對象引用鏈相連時說明該對象不再可用摄闸,GC root對象包括四種:方法區(qū)中常量和靜態(tài)變量引用的對象善镰,虛擬機棧中變量引用的對象,本地方法棧中引用的對象; 解決循環(huán)引用是因為GC Root通常是一組特別管理的指針年枕,這些指針是tracing GC的trace的起點炫欺。它們不是對象圖里的對象,對象也不可能引用到這些“外部”的指針熏兄。
    • 采用引用計數(shù)算法的系統(tǒng)只需在每個實例對象創(chuàng)建之初品洛,通過計數(shù)器來記錄所有的引用次數(shù)即可树姨。而可達性算法,則需要再次GC時桥状,遍歷整個GC根節(jié)點來判斷是否回收
java對象的四種引用
  • 強引用 :創(chuàng)建一個對象并把這個對象直接賦給一個變量帽揪,eg :Person person = new Person(“sunny”); 不管系統(tǒng)資源有么的緊張,強引用的對象都絕對不會被回收辅斟,即使他以后不會再用到台丛。
  • 軟引用 :通過SoftReference類實現(xiàn),eg : SoftReference p = new SoftReference(new Person(“Rain”));內(nèi)存非常緊張的時候會被回收砾肺,其他時候不會被回收挽霉,所以在使用之前要判斷是否為null從而判斷他是否已經(jīng)被回收了。
  • 弱引用 :通過WeakReference類實現(xiàn)变汪,eg : WeakReference p = new WeakReference(new Person(“Rain”));不管內(nèi)存是否足夠侠坎,系統(tǒng)垃圾回收時必定會回收
  • 虛引用 :不能單獨使用,主要是用于追蹤對象被垃圾回收的狀態(tài)裙盾,為一個對象設(shè)置虛引用關(guān)聯(lián)的唯一目的是希望能在這個對象被收集器回收時收到一個系統(tǒng)通知实胸。通過PhantomReference類和引用隊列ReferenceQueue類聯(lián)合使用實現(xiàn)
點我了解更多JAVA的內(nèi)管管理機制
再次回到OC——>

所有權(quán)修飾符

id __strong obj0;  
id __weak obj1;  
id __autoreleasing obj2;  
// __strong,__weak,__autoreleasing可以保證附有這些修飾符的自動變量初始化為nil  
  
// 上面源碼和下面效果等同  
id __strong obj0 = nil;  
id __weak obj1 = nil;  
id __autoreleasing obj2 = nil;  
__strong修飾符

__strong修飾符是id類型和對象類型默認的所有權(quán)修飾符。也就是說番官,以下源代碼中的id變量庐完,實際上被附加了所有權(quán)修飾符。

id obj = [[NSObject alloc] init];

id和對象類型在沒有明確指定所有權(quán)修飾符時徘熔,默認為__strong修飾符门躯。上面的源代碼與以下相同。

id __strong obj = [[NSObject alloc] init];

該源代碼在ARC無效時的表述為:

/* ARC 無效 */
id obj = [[NSObject alloc] init];

該源代碼一看則明酷师,目前在表面上沒有任何變化讶凉。再看看下面的代碼。

{
  id __strong obj = [[NSObject alloc] init];
}

此源代碼明確指定了C語言的變量作用域山孔。ARC無效時懂讯,該源代碼可記述如下:

/* ARC 無效 */
{
  id __strong obj = [[NSObject alloc] init];
  [obj release];
}

為了釋放生詞并持有的對象,增加了調(diào)用release方法的代碼台颠。動作同先前ARC有效時動作完全一樣褐望。
如“strong”這個名稱所示,__strong修飾符表示對對象的“強引用”串前。持有強引用的變量在超出其作用域時被廢棄瘫里,隨著強引用的失效,引用的對象會隨之釋放酪呻。

{
    /*
     * 自己生成并持有對象
     */ 
     id __strong obj = [[NSObject alloc] init];
     
    /*
     * 因為變量 obj 為強引用减宣,
     * 所以自己持有對象
     */ 
}
    /*
     * 因為變量 obj 超出其作用域盐须,強引用失效玩荠,
     * 所以自動地釋放自己持有的對象。
     * 對象的所有者不存在,因此廢棄該對象阶冈。
     */ 

此處闷尿,對象的所有者和對象的生存周期是明確的。那么女坑,在取得非自己生成并持有的對象時又會如何呢填具?

{
     id ___strong obj = [NSMutableArray array];
}

在NSMutableArray 類的 array 類方法的源代碼中取得非自己生成的對象,具體如下:

{
    /*
     * 取得非自己生成的對象
     */ 
      id ___strong obj = [NSMutableArray array];
     
    /*
     * 因為變量 obj 為強引用匆骗,
     * 所以自己持有對象
     */ 
}
    /*
     * 因為變量 obj 超出其作用域劳景,強引用失效,
     * 所以自動地釋放自己持有的對象碉就。
     */ 

附有__strong修飾符的變量之間可以相互賦值盟广。

正如蘋果宣稱的那樣,通過__strong修飾符瓮钥,不必再次鍵入retain或release筋量,完美地滿足了“引用計數(shù)式內(nèi)存管理的思考方式”。因為id類型和對象類型的所有權(quán)修飾符默認為__strong修飾符碉熄,所以不需要寫上“__strong”桨武。使ARC有效及簡單的編程遵循了Objective-C內(nèi)存管理的思考方式。

__weak修飾符

__weak用來避免“循環(huán)引用”問題锈津。

例如前面出現(xiàn)帶有__strong 修飾符的成員變量在持有對象時呀酸,很容易發(fā)生循環(huán)引用。

@interface Test : NSObject
{
    id __strong obj_;
}
- (void)setObject:(id __strong)obj;
@end

@implementation Test
- (id)init
{
    self = [super init];
    return self;
}
- (void)setObject:(id __strong)obj
{
    obj_ = obj;
}

以下為循環(huán)引用琼梆。

{
    id test0 = [[Test alloc] init]; // 對象A 七咧。test0持有Test對象A的強引用

    id test1 = [[Test alloc] init]; // 對象B。 test1持有Test對象B的強引用

    [test0 setObject:test1];
    /*
     * Test 對象 A 的 obj_成員變量持有Test對象 B 的強引用叮叹。
     *
     * 此時艾栋,持有Test對象 B 的強引用的變量為
     * Test 對象 A 的obj_和test1。
     */

    [test1 setObject:test1];
     /*
     * Test 對象 B 的 obj_成員變量持有Test對象 A 的強引用蛉顽。
     *
     * 此時蝗砾,持有Test對象 A 的強引用的變量為
     * Test 對象 B 的obj_和test0。
     */
}
     /*
     * 因為 test0 變量超出其作用域携冤,強引用失效悼粮。
     * 所以自動釋放 Test 對象 A。
     * 
     * 因為 test1 變量超出其作用域曾棕,強引用失效扣猫。
     * 所以自動釋放 Test 對象 B。
     * 
     * 此時翘地,持有Test對象 A 的強引用的變量為
     * Test 對象 B 的obj_申尤。
     * 
     * 此時癌幕,持有 Test 對象 B 的強引用的變量為
     * Test 對象 A 的obj_。
     * 
     * 發(fā)生內(nèi)存泄漏昧穿!
     */

循環(huán)引用容易發(fā)生內(nèi)存泄漏勺远。所謂內(nèi)存泄漏就是應(yīng)當廢棄的對象在超出其生存周期后繼續(xù)存在。
像下面這種情況时鸵,雖然只有一個對象胶逢,但在該對象持有其自身時,也會發(fā)生循環(huán)引用(自引用)饰潜。

    id test = [[Test alloc] init];
    [test setObject:test];

__weak 修飾符與 __strong 修飾符相反初坠,提供弱引用。弱引用不能持有對象實例彭雾。

{
    /*
     * 自己生成并持有對象
     */ 
      id ___strong obj0 = [[NSObject alloc] init];
    /*
     * 因為變量 obj0 為強引用某筐,
     * 所以自己持有對象
     */ 

      id __weak obj1 = obj0;
   /*
     * 因為變量 obj0 為強引用,
     * 所以自己持有對象
     */ 
}
    /*
     * 因為變量 obj0 超出其作用域冠跷,強引用失效南誊,
     * 所以自動地釋放自己持有的對象。
     * 因為對象的所有者不存在蜜托,所以廢棄該對象抄囚。
     */ 

__weak 修飾符還有另一有點。在持有某對象的弱引用時橄务,若該對象被廢棄幔托,則此弱引用將自動失效且處于nil被復制的狀態(tài)(空弱應(yīng)用)。如以下代碼所示蜂挪。

id __weak obj1 = nil;
{
    id __strong obj0 = [[NSObject alloc] init];
    obj1 = obj0;
    NSLog(@"A: %@", obj1);
}
NSLog(@"B: %@", obj1);

此源代碼執(zhí)行結(jié)果如下:

A: <NSObject: 0x753e180>
B: (null)

遺憾的是重挑,__weak 修飾符只能用于iOS5以上及OS X Lion以上版本的應(yīng)用程序。在iOS4以及OS X Snow Leopard的應(yīng)用程序中使用__unsafe_unretained 修飾符來代替棠涮。

__unsafe_unretained 修飾符

__unsafe_unretained 修飾符正如其名unsafe所示谬哀,是不安全的所有權(quán)修飾符。

  • __unsafe_unretained: 不會對對象進行retain,當對象銷毀時,會依然指向之前的內(nèi)存空間(野指針)
  • __weak: 不會對對象進行retain,當對象銷毀時,會自動指向nil
已經(jīng)有了__weak 為什么還要保留 __unsafe_unretained 严肪?
__autoreleasing 修飾符

ARC有效時不能使用autorelease方法史煎,也不能使用NSAutoreleasePool類。雖然autorelease無法直接使用驳糯,但實際上篇梭,ARC有效時 autolease功能是起作用的。

    /* ARC 無效 */
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    id obj = [[NSObject alloc] init];
    [obj autorelease];
    [pool darin];// 此處等同于 “[obj release]”

ARC有效時酝枢,鈣源代碼也能寫成下面這樣恬偷,

    @autoreleasepool {
        id __autoreleasing obj = [[NSObject alloc] init];          
    }

指定“@autoreleasepool塊”來代替“NSAutoreleasePool類對象生成、持有以及廢棄”這一范圍帘睦。
另外袍患,ARC有效時坦康,要通過將對象賦值給附加了 __autoreleasing修飾符的變量來代替調(diào)用autorelease方法。對象賦值給附有__autoreleasing修飾符的變量等價于在ARC無效時調(diào)用對象的autorelease方法协怒,即對象被注冊到autoreleasepool涝焙。

但是卑笨,顯示地附加 __autoreleasing修飾符同顯示地附加__strong修飾符一樣罕見孕暇。
編譯器會檢查方法名是否以alloc/new/copy/mutableCopy開始,如果不是則自動將返回值的對象注冊到autoeleasepool赤兴。

規(guī)則

在ARC有效的情況下編譯源代碼妖滔,必須遵守一定的規(guī)則。

  • 不能使用 retain/release/retainCount/autorelease
  • 不能使用 NSAllocateObject/NSDeallocateObject
  • 須遵守內(nèi)存管理的方法命名規(guī)則
  • 不要顯式調(diào)用dealloc
  • 不能使用區(qū)域(NSZone)
  • 對象型變量不能作為C語言結(jié)構(gòu)體(struct/union)的成員
  • 顯示轉(zhuǎn)換“id”和“void *”

遵守內(nèi)存管理的方法命名規(guī)則桶良。

在ARC無效時座舍,用于對象生成/持有的方法必須遵守以下的命名規(guī)則。

  • alloc
  • new
  • copy
  • mutableCopy

以上述名稱開始的方法在返回對象時陨帆,必須返回給調(diào)用方所應(yīng)當持有的對象曲秉。這在ARC有效時也一樣,返回的對象完全沒有改變疲牵。只是在ARC有效時要追加一條命名規(guī)則承二。

  • init

以 init 開始的方法的規(guī)則要比 alloc/new/copy/mutableCopy 更嚴格。該方法必須是實例方法纲爸,并且必須要返回對象亥鸠。返回的對象應(yīng)為id類型或該方法聲明類的對象類型,抑或是該類的超類型或子類型识啦。

屬性

當ARC有效時负蚊,Objective-C類的屬性也會發(fā)生變化。

@property (nonatomic, strong) NSString *name;

當ARC有效時颓哮,以下可作為這種屬性聲明中使用的屬性來用家妆。如表1-3所示。

表1-3 屬性聲明的屬性與所有權(quán)修飾符的對應(yīng)關(guān)系
屬性聲明的屬性 所有權(quán)修飾符
assign __unsafe_unretained 修飾符
copy __strong 修飾符(但是賦值的是被復制的對象)
retain __strong 修飾符
strong __strong 修飾符
unsafe_unretained __unsafe_unretained 修飾符
weak __weak 修飾符

assign與weak冕茅,它們都是弱引用聲明類型揩徊,最大的區(qū)別在那呢?
如果用weak聲明的變量在棧中就會自動清空嵌赠,賦值為nil塑荒。
如果用assign聲明的變量在棧中可能不會自動賦值為nil,就會造成野指針錯誤姜挺!

  • 修飾變量類型的區(qū)別
    weak 只可以修飾對象齿税。如果修飾基本數(shù)據(jù)類型,編譯器會報錯-“Property with ‘weak’ attribute must be of object type”炊豪。
    assign 可修飾對象凌箕,和基本數(shù)據(jù)類型拧篮。當需要修飾對象類型時,MRC時代使用unsafe_unretained牵舱。當然串绩,unsafe_unretained也可能產(chǎn)生野指針,所以它名字是"unsafe_”芜壁。
  • 是否產(chǎn)生野指針的區(qū)別
    weak 不會產(chǎn)生野指針問題礁凡。因為weak修飾的對象釋放后(引用計數(shù)器值為0),指針會自動被置nil慧妄,之后再向該對象發(fā)消息也不會崩潰顷牌。 weak是安全的。
    assign 如果修飾對象塞淹,會產(chǎn)生野指針問題窟蓝;如果修飾基本數(shù)據(jù)類型則是安全的。修飾的對象釋放后饱普,指針不會自動被置空运挫,此時向?qū)ο蟀l(fā)消息會崩潰。
以上部分內(nèi)容是摘自Kazuki Sakamoto Tomohiko Furumoto 著的《Objective-C高級編程 iOS與OS X多線程和內(nèi)存管理》一書中的第一章“自動引用計數(shù)”套耕。有興趣深入了解的朋友可以看看谁帕。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市箍铲,隨后出現(xiàn)的幾起案子雇卷,更是在濱河造成了極大的恐慌,老刑警劉巖颠猴,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件关划,死亡現(xiàn)場離奇詭異,居然都是意外死亡翘瓮,警方通過查閱死者的電腦和手機贮折,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來资盅,“玉大人调榄,你說我怎么就攤上這事『强福” “怎么了影锈?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵舞竿,是天一觀的道長鳞贷。 經(jīng)常有香客問我怎诫,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任腮出,我火速辦了婚禮帖鸦,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘胚嘲。我一直安慰自己作儿,他們只是感情好,可當我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布馋劈。 她就那樣靜靜地躺著攻锰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪侣滩。 梳的紋絲不亂的頭發(fā)上口注,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天变擒,我揣著相機與錄音君珠,去河邊找鬼。 笑死娇斑,一個胖子當著我的面吹牛策添,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播毫缆,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼唯竹,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了苦丁?” 一聲冷哼從身側(cè)響起浸颓,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎旺拉,沒想到半個月后产上,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡蛾狗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年晋涣,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沉桌。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡谢鹊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出留凭,到底是詐尸還是另有隱情佃扼,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布蔼夜,位于F島的核電站兼耀,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏挎扰。R本人自食惡果不足惜翠订,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一巢音、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧尽超,春花似錦官撼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至巩踏,卻和暖如春秃诵,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背塞琼。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工菠净, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人彪杉。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓毅往,卻偏偏與公主長得像,于是被迫代替她去往敵國和親派近。 傳聞我的和親對象是個殘疾皇子攀唯,可洞房花燭夜當晚...
    茶點故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 1.1 什么是自動引用計數(shù) 概念:在 LLVM 編譯器中設(shè)置 ARC(Automaitc Reference Co...
    __silhouette閱讀 5,115評論 1 17
  • 1.1 自動引用計數(shù)(ARC,Automatic Reference Counting) 自動引用計數(shù)是指內(nèi)存管理...
    SkyMing一C閱讀 1,078評論 0 5
  • 29.理解引用計數(shù) Objective-C語言使用引用計數(shù)來管理內(nèi)存侯嘀,也就是說,每個對象都有個可以遞增或遞減的計數(shù)...
    Code_Ninja閱讀 1,475評論 1 3
  • 光芒下的人形是恍惚和刺眼的谱轨,背對著陽光遮蓋住過往和翅膀戒幔,而正對著你的人是五官模糊的。那層模糊是擦不掉的油漆碟嘴,也是...
    野不言閱讀 178評論 0 1
  • 感恩宇宙賜予我美好溪食,感恩大地滋養(yǎng)萬物惠及我,感恩陽光普照給我光明娜扇,感恩父母給予生命讓我健康成長错沃,感恩每天身邊發(fā)生的...
    liuxiaorui閱讀 91評論 0 0