OC 內存管理:MRC與ARC

 
 
內存中的五大區域:
棧區,堆區,BBS段,數據段和代碼段,其中除了堆區之外,其餘區域的內存管理由系統自行回收
OC對象是存儲在堆區的,因此OC的內存管理主要是對」堆區中的OC對象」進行管理
 
內存管理中的幾個概念:
->引用計算器:既retainCount,每一個OC對象內部都有1個8字節空間用來存儲retainCount,表示有多少」人」正在使用;
對象剛被建立時,默認計數值就爲1,當計數值爲0時,系統會自動調用dealloc方法將對象銷燬
引用計數器的用法:給對象發送相應的技術操做來改變計數器的值
     retain消息:使計數器+1
     release消息:使計數器-1
      retainCount消息:獲得當前當前retainCount的值
->野指針:沒有初始化的指針變量
->殭屍對象:指一個對象已經被回收,但其數據還存在內存中
殭屍對象有可能能夠訪問,也有可能不能訪問,取決於所佔用空間是否已被從新分配.然而,對象一旦被回收就不應再被訪問,此時能夠開啓殭屍對象檢測,這樣系統會自動檢查是否爲殭屍對象,但同時也會下降執行效率.
->內存泄露:指對象沒有在該回收的時候被回收,而是一直駐留在內存中,直到程序結束的時候才被釋放
 
內存管理的分類:
->MRC:Manual Reference Counting,既手動內存管理
對引用計數器的操做全由程序員親自完成
->ARC:Automatic Reference Counting,既自動內存管理 
(垃圾回收不能在iOS系統使用,故此處暫不討論)
系統會依照程序員的要求自動改變引用計數器的值(Xcode6開始,默認使用ARC)
 
手動內存管理:
->手動內存管理的原則:
1)一旦建立一個對象,這個對象的引用計數器的值就爲1,因此必需要匹配1個release
2)只有在多1我的使用這個對象的時候才retain
   只有在燒1我的使用這個對象的時候才release
3)retain的次數要和release次數相匹配
4)永遠不要手動調用對象的dealloc方法,而是讓系統自動調用
->手動內存管理中內存泄露的幾種狀況:
1) retain和release不匹配,retain多餘release致使的內存泄露;
2) 對象使用過程當中,沒有被release,而被賦值爲nil;
3) 在方法中不當的使用了retain;
手動內存管理的關鍵就是防止內存泄露!!!!!防止內存泄露要記住:
1) 誰建立」alloc","new",誰"release";
2) 誰」retain",誰"release";
->多對象的手動內存管理:
當B類做爲A類屬性時,要防止內存泄露,則A類的setter方法應爲:
其中setter方法實現還可寫成:
以上是標準的MRC內存管理代碼.
->循環retain問題:
1) 遇到的問題:
    當兩個對象相互引用的時候.
    A對象的屬性指向B對象, B對象的屬性指向A對象.
    這個時候,若是兩邊都使用retain.就會出現內存泄露. 都回收不了.
2) 解決方案:
    1端使用retain,1端使用assign.(請查看@property帶參數用法的相關內容) 
    須要注意的是: 使用assign的那1段,dealloc中不須要再去release這個對象了.
->自動釋放池(autorelease)
1)原理:
存儲在自動釋放池的對象,在自動釋放池銷燬時,會自動調用該對象的release方法,故將對象存儲在自動釋放池中,就不須要再寫release
2)建立方法:
@autorelease
{
} //大括弧表示自動釋放池的範圍
3)將對象放入的方法:
在自動釋放池的範圍中調用對象的autorelease方法.注:autorelease的返回值是對象自己,因此咱們能夠這樣建立對象:
@autorelease
{
類型 *對象 = [類名 alloc] init] autorelease];
}
4)使用注意:
      a.只有在自動釋放池中調用了對象的autorelease方法,這個對象纔會被存儲到這個自動釋放池之中
     b. 對象的建立能夠在自動釋放池的外面,在自動釋放池之中,調用對象的autorelease方法,就能夠將這個對象存儲到這個自動釋放池之中.
   c. 當自動釋放池結束的時候.僅僅是對存儲在自動釋放池中的對象發送1條release消息 而不是銷燬對象.
   d. 若是在自動釋放池中,調用同1個對象的autorelease方法屢次.就會將對象存儲屢次到自動釋放池之中.在自動釋放池結束的時候.會爲對象發送多條release消息.那麼這個時候就會出現殭屍對象錯誤.
     e. 自動釋放池能夠嵌套.調用對象的autorelease方法,會講對象加入到當前自動釋放池之中,只有在當前自動釋放池結束的時候纔會像對象發送release消息.
5)使用規範:
咱們通常狀況下,寫1個類.會爲咱們的類寫1個同名的類方法,用來讓外界調用類方法來快速的獲得1個對象.應遵照規範:使用類方法建立的對象,要求這個對象在方法中就已經被autorelease過了.這樣,咱們只要在自動釋放池中, 調用類方法來建立對象, 那麼建立的對象就會被自動的加入到自動釋放中.
 
自動內存管理:
->自動內存管理原則: 編譯器會自動的在合適的地方插入retain、release、autorelase代碼;編譯器自動爲對象作引用計數. 而做爲開發者,徹底不須要擔憂編譯器會作錯(除非開發者本身錯用了ARC).
->強指針與弱指針:
強指針:默認狀況下,咱們聲明的指針都爲強指針,也可使用__strong來顯示的聲明指針爲強指針.
弱指針:使用__weak關鍵字修飾的指針,例如 __weak Person *p;
做用與區別:在ARC模式下,強指針與弱指針用來做爲回收對象的標準,當1個對象即便用弱指針指向,但沒有任何強指針指向時就會被當即回收,此時該弱指針會被自動設置爲nil.
->ARC模式下的循環引用:
在ARC機制下,若是出現了循環引用,既A對象中有1個屬性是B對象. B對象中有1個屬性是A對象.此時若是兩邊都爲strong.就會發生內存泄露.
解決方案:1端使用strong 另外1端使用weak
 
 
 
 MRC和ARC的轉換與兼容:
#  ARC兼容MRC的類
target --> Build Phaese   --->   Compiler Sources --> Compiler Flags
讓程序兼容ARC和非ARC部分。
轉變爲非ARC  -fno-objc-arc
轉變爲ARC的, -f-objc-arc
#  MRC轉ARC
Xcode —> refactor  -->   Convert to Objective-C ARC   選中要裝換的target -->  調校代碼
相關文章
相關標籤/搜索