ARC在OC裡面個人感覺又是一個高大上的牛詞,在前面Objective-C中的記憶體管理部分提到了ARC記憶體管理機制,ARC是Automatic Reference Counting---自動引用計數。有自動引用計數,那麼就得有手動引用計數MRC(Mannul Reference Counting),前面已經提到過了MRC。那麼在ARC模式下是不是意味着我們就可以一點也不用進行記憶體管理的呢?并不是這樣的,我們還需要代碼進行記憶體的管理。下面會結合着代碼把OC中的ARC機制做一個詳細的總結(歡迎大家批評指針,轉載請注明出處 )。
在ARC機制下是少不了下面這些東西的:
1.關鍵字 __strong 預設值,表示隻要有強引用指針指向該變量,則該變量會一直存在。
2.關鍵字__weak 弱引用,表示若沒有任何強引用指針指向該變量,會自動将變量的值置為空,即nil狀态。
3.關鍵字 __autoreleasing 用于标示自動釋放的變量
4.__unsafe_unretained 不安全的弱引用,若沒有任何強引用指針指向該變量,不會自動設為空,會成為野指針。
關于Weak和Strong,看下圖吧:
第一次接觸ARC的小夥伴們看到上面的概念可能會一頭霧水,上面說的是個啥?都是哪跟哪?不用着急,下面會有執行個體代碼,結合着執行個體代碼,然後再做一個總結,你就會有種豁然開朗的感覺。你就會明白,哦,原來ARC是這麼一回事。好啦,廢話少說,用代碼講東西才是王道,代碼走起。(為了友善我們觀察記憶體的釋放情況,可以設定斷點來單步運作)
為了做測試使用,我們建一個測試類,并重寫dealloc方法來觀察記憶體的釋放情況,測試類如下;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
一.__strong: 強引用,是ARC中變量聲明的預設值,用大白話講就是你手動配置設定的堆記憶體,如果沒有指針指向這塊記憶體,那麼這塊記憶體就會被回收
1.當聲明變量為強引用時,對象的指針出棧時,如果該指針指向的記憶體空間沒有别的指針指向他,就自動掉用dealloc方法釋放堆記憶體測試代碼如下:
|
代碼運作結果:
|
代碼說明:從運作結果來看,出代碼塊後我們定于的指針變量會随着我們代碼塊的結束而釋放,就沒有指針指向我們配置設定的堆記憶體了,以為預設為strong,是以在ARC機制下會立即調用dealloc來釋放堆記憶體。
2.給對象指針重寫配置設定記憶體的情況,代碼如下:
|
|
代碼說明:我們先給strong類型的對象指針配置設定記憶體空間,然後再次配置設定記憶體空間,在第二次配置設定空間的時候,就沒有對象指針指向原有的記憶體空間,是以在第二次配置設定空間之後就會把原有的記憶體空間給釋放掉,在出代碼塊的時候,對象指針也會随着棧記憶體的釋放而釋放掉,也沒有對象指針指向第二次配置設定的記憶體了,是以會被釋放掉。
3.把對象指針置為空時,配置設定的堆記憶體會立即被釋放掉。相應的代碼如下:
|
|
代碼說明:把指向該記憶體空間的對象指針置空,就相當于沒有指針指向該記憶體空間,是以在strong下會被立即釋放。
4.把新的對象指針指向堆記憶體空間,然後把原有的指針進行置空
代碼如下:
|
運作結果:
|
代碼說明:當兩個指針同時指向一塊記憶體空間時,把原有的指針置為空,這塊記憶體空間不會被釋放的,因為還有其他的指針指向該記憶體空間。
二. __weak 歸零弱引用:在若指針指向的記憶體被釋放後,若引用的指針則會置零
歸零弱引用:弱引用的指針指向強引用的記憶體時,是不影響其釋放記憶體空間的,當弱引用指針所指空間被釋放掉得時候,該弱引用指針會被置零。
代碼如下
|
運作結果如下:
|
代碼說明:當出大括号時強引用指針會被釋放掉,之前開辟的堆記憶體空間隻有一個弱引用指針指向他,是以在ARC中會被自動釋放,弱引用指針會置零。
三. __autoreleasing 自動釋放,一般結合着@autoreleasepool使用。
1.自動釋放修飾的指針所指向的記憶體空間會在自動釋放池結束的時候會被釋放,代碼如下
|
代碼運作結果:
|
代碼說明:自動釋放池結束後,自動對象指針指向的記憶體空間會被釋放,但上面的用法會産生野指針。
2.__autoreleasing結合着自動釋放池會延遲記憶體空間的釋放
代碼如下:
|
運作結果:
|
代碼說明:由運作結果可以看出即使把指向記憶體空間的自動釋放類型的指針置空,其對應的記憶體空間不像強引用那樣被直接釋放掉,而是等到自動釋放池結束後在釋放,這就是延遲釋放。
3.被自動釋放類型的指針用過的記憶體空間,在自動釋放池結束的時候一樣會被釋放掉。
|
代碼運作結果:
|
代碼說明:上面的代碼可能會引起記憶體洩露,因為如果第一次配置設定空間的時候如果我們往對象裡加入的是一個視訊,那麼在第二次給自動釋放類型的指針配置設定記憶體的時候,前面的記憶體空間不會被釋放掉,直到自動釋放池結束後兩個記憶體空間才會被釋放掉。
四,strong, autoreleasing,weak混在一起的使用情況
在weak中的例子,我們能得到weak和strong同指向一塊記憶體空間,當strong的指針不指向該記憶體空間時,這塊記憶體空間就可以被釋放掉,而weak指針被置零。
記憶體空間隻要有autoreleasing或者strong的指針所持有,就不會被釋放
1.strong和autoreleasing的混用
(1).strong類型的指針指向自動釋放的空間
代碼如下:
18 | |
運作結果如下:
|
運作結果說明:上面是先讓自動釋放類型的指針指向該記憶體空間,然後再使強類型的指針指向該記憶體空間,在出自動釋放池的時候是不會釋放該記憶體空間的,直到強引用指針被釋放掉,才釋放該記憶體空間。
(2).自動釋放類型的指針指向strong類型的指針所配置設定的空間的情況
|
|
結果說明:當strong修飾的指針随着棧的釋放而釋放,但其指向的記憶體空間并沒有被釋放,因為他還被自動釋放類型的指針所持有,是以在出自動釋放池的時候才會被釋放。
(3).strong 類型的指針會指向自動釋放類型的空間記憶體,當strong指針被置空時該記憶體不會被釋放。
代碼如下:
19 | |
代碼運作結果:
|
2.弱類型和自動釋放類型的混用
20 | weak |
|
代碼說明:即使有弱引用類型的指針指向該記憶體空間在出自動釋放池的時候,該記憶體空間也會被釋放。弱引用的指針會被置零。
上面寫了這麼多來點總結性的東西吧:strong 修飾的指針指向的空間如果沒有其他指針就會被釋放掉(weak類型的不算), 自動釋放類型的指針如果沒有其他類型的指針指向該記憶體空間時,當自動釋放池結束後就會釋放。
上面的總結暫且這麼說吧,是根據筆者自己的了解所總結的内容,不免有偏頗之處,歡迎批評指正,轉載請注明出處。
作者:青玉伏案
出處:http://www.cnblogs.com/ludashi/
本文版權歸作者和共部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。
如果文中有什麼錯誤,歡迎指出。以免更多的人被誤導。
收履歷:某網際網路公司,招聘iOS/Android靠譜工程師,入職後,可内部聯系樓主,有小禮品贈送,有意者可郵箱投遞履歷:[email protected]