標籤:
一 . 記憶體管理 包括記憶體配置 和 記憶體清除
1.記憶體管理的範圍 :人和繼承於NSObject類的對象都需要進行記憶體管理,任何非物件類型的對象(基礎資料型別 (Elementary Data Type) 如 int char float double struct enum等)
2.為什麼只有OC對象才需要進行記憶體管理?
OC對象放在堆裡面 非OC對象(基礎資料型別 (Elementary Data Type) 如 int char float double struct enum等)一般放在棧裡面,棧記憶體會被系統自動回收
3.堆和棧
棧(作業系統):有系統自動分配釋放,存放函數的參數值,局部變數的值等.其操作方式類似於資料結構中的棧(先進後出)
堆(作業系統):一般由程式員手動分配釋放,如果程式員不釋放,程式結束時就會被系統回收,分配方式類似於鏈表
4.引用計數器
每個OC對象都有自己的引用計數器 從字面上可以理解成”對象被引用的次數” 也可以理解為有多傷風人正在使用這個對象
引用計數器的作用:引用計數器表示當前有多少人正在使用這個對象 到沒有任何人在使用這個對象時系統就會回收這個對象 也就是說當對象的引用計數為0時,對象佔用的記憶體就會被系統回收.如果系統的引用計數不為0那麼在整個程式運行過程中,他佔用的記憶體就不可能被回收(除非整個程式以經推出)
任何一個對象在剛建立的使用引用計數都為1 當使用 alloc init copy 等建立對象時,對象的引用計數預設為1
5.如何操作引用計數器
給對象發送一個 retain 訊息 可以使引用計數器的值 +1
給對象發送一個 release 訊息 可以使引用計數器的值 -1 ,release 並不代表銷毀\回收對象 僅僅是引用計數值 -1
給一二對象發送 retainCount 訊息 可以得到當前對象的引用計數器值 有時候不準確 很少用 因為常出錯
需要注意的是: release 並不代表銷毀\回收對象 僅僅是引用計數值 -1 只有當引用計數器值減到0 就會釋放
6.dealloc方法
當一個對象的引用計數器為0時,這個對象即將被釋放,其佔用的記憶體被系統回收
對象即將被銷毀時系統會自動給對象發送一條dealloc訊息(因此,從dealloc方法有沒有被調用.就可以判斷對象是否被銷毀)
dealloc函數是系統調用的函數.不可程式員直接調用.一般情況下,會重寫dealloc方法來釋放相關資源,重寫的dealloc方法就相當於對象的遺言,用來處理對象銷毀後的一些後事.一旦重寫了dealloc方法,就必須調用 [super dealloc] 並且放在dealloc方法的最後調用.
注意事項:dealloc方法是系統調用的方法,程式員不可直接調用,需要重寫dealloc方法.一旦對象被回收,它佔用的記憶體就不可再用,如果堅持使用就會導致程式崩潰(野指標錯誤)
二 .MRC(Manual Reference Counting) :所有的對象需要程式員手動管理,需要程式員自己編寫release/retain等方法
1.記憶體管理的原則 :有加就有減 一次alloc就有一次release 一次retain就有一次release
2.野指標 null 指標 殭屍對象
殭屍對象 : 只要一個對象引用計數為0 被釋放 就稱這個對象為殭屍對象
野指標 : 當一個對象指向殭屍對象,我們就成這個指標為野指標 (一個指標指向的對象的引用計數值為0 則這個指標為野指標).只要給野指標發送訊息就會報錯 EXC_BAD_ACCESS
企業開發中 一定要開啟對殭屍對象的監聽
null 指標 : 為了避免給野指標放訊息會報錯,當一個對象被釋放後我們會將這個對象設定成null 指標nil/0. 因為給null 指標發送訊息不會報錯.
3.多個物件的記憶體管理
如果要在A對象和B對象中用C對象 一定要在A對象和B對象中對C對象進行一次retain 當A和B用完後也要對C進行release 一般情況下,A和B對C的retain放在A和B對C的調用函數中,A和B對C的release放在dealloc方法中.其餘的A B C 的自釋放都在原來的主函數中.
就像好幾個人進一個遊戲大廳打遊戲,每進去一個人都要讓大廳記錄+1,當有人離開時,大廳裡人數就會-1.當大廳裡人數紀錄為0時,就大廳釋放.只要還有人,哪怕是一個人也不能釋放大廳.
[email protected]修飾符
readonly:只產生getter方法
readwrite:同時產生getter/setter方法,預設情況下不寫就是readwrite
getter:可以給產生的gutter方法起名稱
setter:可以給產生的setter方法起名稱
retain:會自動幫我們產生setter/gettter方法記憶體管理的代碼
assign:不會替我們產生setter方法的記憶體管理方法,僅僅只是產生普通的gettter/setter方法,預設什麼都不寫就是assign
[email protected]
@class 可以簡單地引用一個類,就是告訴系統這是一個類,可以放心大膽的使用.
具體使用中,在 .h 檔案中使用 @class, 在 .m 檔案中使用 #import包含這個類的 .h 檔案. @class 不拷貝這個類只是告訴編譯器這是一個類,可以使用. #import 會拷貝累的標頭檔.
在用到 @class 時,在 .h 檔案裡 @class,同時在 .m 檔案裡也要 #import,不可省略.
對於迴圈以來的關係使用@class可以避免死迴圈,因為 .h 檔案中的 @class 不做任何拷貝, .m 檔案中的 #import 只會拷貝對應的檔案,不會形成死迴圈.
6.迴圈retain
如果A對象要擁有B對象,且B對象也要擁有A對象.此時就會形成迴圈retain
解決辦法:讓其中一方不要做retain操作
7.autorelease
只要給一個對象發送autorelease訊息,就會將對象放到一個自動釋放池中,當自動釋放池銷毀時,會對池子裡面的所有對象做一次release操作.
注意:這裡只是發送autorelease訊息,如果當時的引用計數值為0,則對象銷毀,否則對象不會被釋放. 調用完autorelease方法後,對象的引用計數值不會改變
autorelease的原理:autorelease實際上只是把對release的調用延遲了,對於每個autorelease系統只是把對象放到當前的自動釋放池中,擋自動釋放池被釋放時,該吃中的所有對象都會被release
三.ARC(Automatic Reference Counting) : 不需要程式員管理記憶體,編譯器會自動給程式議案家release/retain等代碼
1.注意點
iOS中的ARC和java中的記憶體回收機制不同.iOS中的ARC是編譯器在編譯階段自動識別添加release/retain等方法帶代碼中在執行代碼;java中的記憶體回收機制是系統在運行程式是定時檢測垃圾並回收,是系統做的.
2.ARC的判斷原則
使用ARC時只要還有一個強指標變數指向對象,對象就會保持在記憶體中
強指標:被__strong修飾的指標,如果沒有修飾詞,預設的情況下都是強指標,強指標指向的對象會一直儲存在記憶體中
弱指標:被__weak修飾的指標 ,弱指標指向的對象在建立完成後會立即被釋放,無法儲存
3.ARC中的循環參考
在ARC中如果A擁有B,B擁有A,一個用strong 一個用weak,必須有一方使用弱指標
4.ARC中@property參數
strong : 用於OC對象,相當於MRC中的retain
weak : 用於OC對象,相當於MRC中的assign
assign : 用於基礎資料型別 (Elementary Data Type),相當於MRC中的assign
iOS 記憶體管理