iOS-ARC你看我就夠了

注:這一文章將是我自己的復(fù)習(xí)整理過程秀鞭,僅供參考。
(歡迎指出錯誤)

ARC(Automatic Reference Counting)奴紧,是一種對內(nèi)存的管理技術(shù)授帕。
蘋果的文檔中是這么說的:

在Objective-C中采用ARC機制蒲祈,讓編譯器來進(jìn)行內(nèi)存管理捎稚。在新一代Apple LLVM 編譯器中設(shè)置ARC為有效狀態(tài),就無需再次鍵入retain或者release代碼,這在降低程序崩潰徒恋、內(nèi)存泄漏等風(fēng)險的同時,很大程度上減小了開發(fā)程序的工作量溅话。編譯器完全清楚目標(biāo)對象滚秩,并能立刻釋放那些不再被使用的對象。如此一來奈偏,應(yīng)用程序?qū)⒕哂锌深A(yù)測性坞嘀,且能流暢運行,速度也將大幅度提升惊来。

這些優(yōu)點無疑極具吸引能力丽涩,但關(guān)于ARC技術(shù),最重要的還是以下這一點:

“在LLVM編譯器中設(shè)置ARC為有效狀態(tài)裁蚁,就無需再次鍵入retian或者release代碼矢渊。”

C語言需要手動管理內(nèi)存枉证,這種痛苦用過的人應(yīng)該都知道

在OC中內(nèi)存通過引用計數(shù)的方式進(jìn)行管理昆淡。(ARC的本質(zhì)就是自動替我們完成引用計數(shù)的部分)

我們有必要粗略了解一下什么是引用計數(shù)。

<code>
當(dāng)生成一個對象的時候刽严,他就會有一個引用計數(shù)昂灵,那么這數(shù)字將會增大也可能會減小,當(dāng)減小為0的時候舞萄,那么這個對象的內(nèi)存塊將會被釋放眨补。那么引用計數(shù)的關(guān)鍵就在于這個數(shù)字什么時候會增大什么時候會減小。
</code>

思考方式:

  • 自己生成的對象倒脓,自己持有撑螺。
  • 非自己生成的對象,自己也能持有崎弃。
  • 不再需要自己持有的對象時釋放甘晤。
  • 非自己持有的對象無法釋放。

簡單的說持有時引用計數(shù)+1饲做,釋放時引用計數(shù)-1线婚,當(dāng)引用計數(shù)為0的時候,則釋放內(nèi)存盆均。
本文講敘述ARC情況下所引起的變化塞弊。


我們首先必須要理解ARC中追加的所有權(quán)聲明。
ARC有效時所有類型都必須加上所有權(quán)修飾符。所有權(quán)修飾符一共有四種:

  • __strong 修飾符
  • __weak 修飾符
  • __unsafe unretained 修飾符
  • __autoreleasing 修飾符

** __strong 修飾符 **
__strong修飾符是默認(rèn)修飾符游沿,表示對象的“強引用”饰抒,強引用對象在超出其作用域時將會被廢棄,引用的對象釋放诀黍。

<pre>
`
id __strong obj1 = [[NSObject alloc]init];
id __strong obj2 = obj1;
obj1 = nil;
/**
* obj1 = nil, obj2 != nil
*
*/

UIView *view1 = [[UIView alloc]init];
UIView *view2 = view1;

view1.alpha = 0.4;
view2.alpha = 0.5;
/**
 *  view1.alpha = 0.5, view2.alpha = 0.5
 *
 */

`
</pre>

通過上面這段代碼希望大家能明白內(nèi)存管理的思考方式袋坑。
__strong修飾符能夠?qū)ν欢蝺?nèi)存進(jìn)行持有,并共同管理眯勾。

obj1釋放時引用計數(shù)-1咒彤,這個時候只有obj2指向內(nèi)存,因為是強引用咒精,所以這個時候引用計數(shù)仍為1镶柱,所以內(nèi)存并沒有釋放。

  • obj1和obj2的地位相同模叙,也就是都能夠?qū)?nèi)存進(jìn)行管理歇拆。

view1和view2共同管理同一段內(nèi)存,所以當(dāng)view2修改以后范咨,view1的值也會進(jìn)行變化故觅,因為指向同一段內(nèi)存。

__weak 修飾符

然而strong修飾符并不能解決所有問題渠啊,當(dāng)兩個對象相互強引用對方的成員變量的時候输吏,就會發(fā)生循環(huán)引用,循環(huán)引用容易發(fā)生內(nèi)存泄漏替蛉。所謂內(nèi)存泄漏就是應(yīng)當(dāng)廢棄的對象在超出其生命周期后繼續(xù)存在贯溅。那么在這個時候就引入了__weak修飾符,“弱引用”躲查。
因為帶__weak修飾符的變量(即弱引用)不持有對象它浅,所以在超出其作用域時,對象就會釋放镣煮,所以因為強引用而造成的循環(huán)引用姐霍,將其中的成員變量改為弱引用,就不會發(fā)生相同情況典唇。

__weak修飾符還有另外一個優(yōu)點镊折。在持有某若引用時,若該對象被廢棄介衔,則此弱引用將自動失效且處于nil被賦值狀態(tài)(空弱引用)恨胚。如以下代碼所示。
<pre>
`
NSObject __strong *obj1 = [[NSObject alloc]init];
NSObject __weak *obj2 = obj1;

obj1 = nil;
/**
 *  obj1 = nil, obj2 = nil;
 *
 */

`
</pre>

通過使用__weak修飾符可避免循環(huán)引用夜牡。通過檢查附有__weak修飾符的變量是否為nil与纽,可以判斷被賦值對象是否已廢棄。
遺憾的是塘装,__weak修飾符只能用于iOS5以上及OS X Lion以上版本的應(yīng)用程序急迂。在iOS4以及OS X Snow Leopard的應(yīng)用程序中可使用 __unsafe unretained修飾符來代替。

__unsafe unretained 修飾符
__unsafe unretained與weak修飾符一樣不會增加引用計數(shù)蹦肴,自己生成的對象不能繼續(xù)為自己所有僚碎,所以會立即釋放。
那么__unsafe unretained修飾符與weak修飾符有什么區(qū)別呢阴幌?

比如在iOS4以及OS X Snow Leopard的應(yīng)用程序中勺阐,必須使用__unsafe unretained修飾符來替代__weak修飾符。賦值給附有__unsafe unretained修飾符變量的對象在通過該變量使用時矛双,如果沒有確保其存在渊抽,那么應(yīng)用就會崩潰。

__autoreleasing 修飾符

ARC有效時不能使用autorelease方法议忽,同時不能使用NSAutoreleasePool類懒闷。但是,事實上ARC有效時auto lease功能也是起作用的栈幸。
以下兩段代碼是相同的:
<pre>
/*ARC無效*/ NSAutoreleasePool *pool = [[NS NSAutoreleasePool alloc] init]; id obj = [[NSObject alloc] init]; [obj autorelease]; [pool drain];
</pre>
<pre>
/*ARC有效*/ @autoreleasepool { id __autoreleasing obj = [[NSObject alloc]init]; /** * obj 未釋放 * */ } /** * obj已釋放 * */
</pre>

指定“@autoreleasepool塊”來替代“NSAutoreleasePool類對象生成愤估、持有以及廢棄”這一范圍。
另外速址,ARC有效時玩焰,要通過將對象賦值給附加了__autoreleasing修飾符的變量來替代調(diào)用autorelease方法。對象賦值給附有__autoreleasing修飾符的變量等價于在ARC有效時調(diào)用對象的autorelease方法芍锚,即對象被注冊到autoreleasepool昔园。
也就是可以說ARC有效時,用@aotureleasepool塊替代NSAutoreleasePool類并炮,用附有__autoreleasing修飾符的變量替代autorelease方法蒿赢。

因為autoreleasepool范圍以塊級源代碼表示,提高了程序的可讀性渣触,所以今后在ARC無效時也推薦使用@autoreleaseepool塊羡棵。
另外,無論ARC是否有效嗅钻,調(diào)試用的非公開函數(shù)_objc_autoreleasePoolPrint()都可使用皂冰。
_objc_rootRetainCount(obj)
利用這一函數(shù)可有效的幫助我們調(diào)試注冊到autoreleasepool上的對象。


上面講解了四種修飾符养篓,在ARC有效的情況下秃流,必須遵守一定的規(guī)則。下面就是具體的ARC規(guī)則:

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

我們再來看一下ARC有效時屬性與修飾符的對照關(guān)系:

圖片來自----額柳弄,我在書上拍的

最后我們來看一下ARC中自動引用計數(shù)的數(shù)值究竟是多少

我們來看這段代碼:

<pre>
`
{
id __strong obj = [[NSObject alloc]init]; // retian count = 1;

    id __weak o = obj;                          // retian count = 1;
}

//retain count = 0;
`
</pre>

和我們預(yù)期的一樣舶胀,__strong修飾符使引用技術(shù)+1概说,而__weak修飾符,并不會使修飾符+1嚣伐,早超出obj的作用域以后糖赔,引用技術(shù)-1,同時釋放轩端。

我們再來看一下用__autoreleasing修飾符向autoreleasepool注冊會怎么樣:

<pre>
`
@autoreleasepool {

    id __strong obj = [[NSObject alloc]init];   // retian count = 1;
    
    id __autoreleasing o = obj;                 // retian count = 2;
}
//retain count = 0;

`
</pre>

__autoreleasing修飾符放典,使引用計數(shù)+1,而在超出autoreleasepool以后則清空并釋放基茵。

最后再來看一下在autoreleasepool中使用__weak修飾符是什么樣的:

<pre>
`
@autoreleasepool {

    id __strong obj = [[NSObject alloc]init];   // retian count = 1;
    id __weak o = obj;                 // retian count = 2;
}

`
</pre>

在autoreleasepool中即使不使用autoreleasing修飾符奋构,而用__weak修飾符替代,同樣將obj對象注冊到了autoreleasepool中拱层。


這篇文章大體上記敘ARC中自動計數(shù)的表現(xiàn)弥臼,其中包括一些我的理解,和參考書的摘抄根灯。歡迎指出錯誤醋火。

如果覺得我寫的不錯,請關(guān)注我箱吕。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末芥驳,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子茬高,更是在濱河造成了極大的恐慌兆旬,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件怎栽,死亡現(xiàn)場離奇詭異丽猬,居然都是意外死亡,警方通過查閱死者的電腦和手機熏瞄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進(jìn)店門脚祟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人强饮,你說我怎么就攤上這事由桌。” “怎么了邮丰?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵行您,是天一觀的道長。 經(jīng)常有香客問我剪廉,道長娃循,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任斗蒋,我火速辦了婚禮捌斧,結(jié)果婚禮上笛质,老公的妹妹穿的比我還像新娘。我一直安慰自己捞蚂,他們只是感情好妇押,可當(dāng)我...
    茶點故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著洞难,像睡著了一般舆吮。 火紅的嫁衣襯著肌膚如雪揭朝。 梳的紋絲不亂的頭發(fā)上队贱,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天,我揣著相機與錄音潭袱,去河邊找鬼柱嫌。 笑死,一個胖子當(dāng)著我的面吹牛屯换,可吹牛的內(nèi)容都是我干的编丘。 我是一名探鬼主播,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼彤悔,長吁一口氣:“原來是場噩夢啊……” “哼嘉抓!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起晕窑,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤抑片,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后杨赤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體敞斋,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年疾牲,在試婚紗的時候發(fā)現(xiàn)自己被綠了植捎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡阳柔,死狀恐怖焰枢,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情舌剂,我是刑警寧澤医咨,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站架诞,受9級特大地震影響拟淮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜谴忧,卻給世界環(huán)境...
    茶點故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一很泊、第九天 我趴在偏房一處隱蔽的房頂上張望角虫。 院中可真熱鬧,春花似錦委造、人聲如沸戳鹅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽枫虏。三九已至,卻和暖如春爬虱,著一層夾襖步出監(jiān)牢的瞬間隶债,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工跑筝, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留死讹,地道東北人。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓曲梗,卻偏偏與公主長得像赞警,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子虏两,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,543評論 2 349

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