注:這一文章將是我自己的復(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)注我箱吕。