ARC對self的內(nèi)存管理

來源:http://blog.sunnyxx.com/2015/01/17/self-in-arc/

記錄下前兩天的一次討論,源于網(wǎng)絡(luò)庫YTKNetwork“YTKRequest.m”的- start方法其中的幾行代碼:

- (void)start {

// ......

YTKRequest *strongSelf =self;

[strongSelf.delegate requestFinished:strongSelf];

if(strongSelf.successCompletionBlock) {

strongSelf.successCompletionBlock(strongSelf);

}

[strongSelf clearCompletionBlock];

}

看起來比較有違常理,所以和猿題庫的@晨鈺Lancy,@唐巧以及網(wǎng)易的@老漢一起討論了下這個問題。

具體的問題大概是這樣:

調(diào)用方(如view controller)實例化并強引用YTKRequest對象,將自己作為其delegate

調(diào)用方調(diào)用YTKRequest的- start方法發(fā)起網(wǎng)絡(luò)請求

調(diào)用方在- requestFinished:中執(zhí)行了self.request = nil;

YTKRequest中,- start方法在回調(diào)完- requestFinished:后BAD_ACCESS

也就是說,- start方法還未返回時,self就被外部釋放了。作者發(fā)現(xiàn)了這個潛在的問題,所以在方法局部增設(shè)了一個strongSelf的強引用來保證self的生命周期延續(xù)到方法結(jié)束。問題是解決了,但是更希望知道原因。

簡化說明就是:

- (void)foo {

// self被delegate持有

[self.delegate callout];// 外部釋放了這個對象

// 這里self野指針

}

現(xiàn)在想想還是比較不符合常理,入?yún)⒌膕elf居然不能保證這個函數(shù)執(zhí)行完成。后來查閱了下文檔,發(fā)現(xiàn)是ARC的(gao)機(de)制(gui),clang的《這篇ARC文檔》中有明確的解釋,總結(jié)如下:

ARC下,self既不是strong也不是weak,而是unsafe_unretained的,也就是說,入?yún)⒌膕elf被表示為:(init系列方法的self除外)

- (void)start {

const__unsafe_unretained YTKRequest *self;

// ...

}

在方法調(diào)用時,ARC不會對self做retain或release,生命周期全由它的調(diào)用方來保證,如果調(diào)用方?jīng)]有保證,就會出現(xiàn)上面的crash

ARC這樣做的原因是性能優(yōu)化,objc中100%的方法(不是函數(shù))調(diào)用第一個參數(shù)都是self,同時,99%的情況下,調(diào)用方都不會在方法執(zhí)行時把這個對象釋放,所以相比于在每個方法中插入對self的引用計數(shù)管理:

- (void)start {

objc_retain(self);

// 其中的代碼self一定不會被釋放

objc_release(self);

}

優(yōu)化了的性能還真是比較可觀。

而且,ARC也用了挺多方法來避免開發(fā)者進行額外的引用計數(shù)控制,比如方法的命名約定,通過判斷方法是否以如init,alloc,new,copy等關(guān)鍵字開頭來決定其內(nèi)存管理方式。

One more thing

在寫test時發(fā)現(xiàn),下面兩種調(diào)用方法會導(dǎo)致不同結(jié)果:

- (void)viewDidLoad {

// 1

[_request start];// crash

// 2

[self.request start];// 正常

}

因為self.request是一次方法調(diào)用,返回的結(jié)果被objc_retainAutoreleasedReturnValue方法在局部進行了一次強引用,關(guān)于這個方法可以看之前寫過的關(guān)于Autorelease的《這篇文章》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,103評論 0 9
  • 禪與 Objective-C 編程藝術(shù) (Zen and the Art of the Objective-C C...
    GrayLand閱讀 1,842評論 1 10
  • ARC的本質(zhì) ARC是編譯器(時)特性,而不是運行時特性,更不是垃圾回收器(GC)。 Automatic Refe...
    成熱了閱讀 707評論 0 1
  • 『一整個宇宙,換一顆紅豆?!?沿著歲月的足跡,尋覓經(jīng)年花開的聲響。跌在記憶里的風(fēng),還在四處奔跑,不知道你的眼角眉梢...
    快樂本本書閱讀 384評論 0 0
  • 朋友送我新茶,茶在清水的浸潤中,綠色從干枯中重生,香氣由苦澀中醞釀,宛如一段曲折的人生經(jīng)歷……經(jīng)得起炙烤與烘...
    王藝璇媽媽閱讀 282評論 0 10

友情鏈接更多精彩內(nèi)容