一 . 記憶體管理 包括記憶體分配 和 記憶體清除

1.記憶體管理的範圍 :人和繼承於NSObject類的物件都需要進行記憶體管理,任何非物件型別的物件(基本資料型別 如 int char float double struct enum等)

2.為什麼只有OC物件才需要進行記憶體管理?

OC物件放在堆裡面 非OC物件(基本資料型別 如 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.野指標 空指標 殭屍物件

殭屍物件 : 只要一個物件引用計數為0 被釋放 就稱這個物件為殭屍物件

野指標 : 當一個物件指向殭屍物件,我們就成這個指標為野指標 (一個指標指向的物件的引用計數值為0 則這個指標為野指標).只要給野指標傳送訊息就會報錯 EXC_BAD_ACCESS

企業開發中 一定要開啟對殭屍物件的監聽

空指標 : 為了避免給野指標放訊息會報錯,當一個物件被釋放後我們會將這個物件設定成空指標nil/0. 因為給空指標傳送訊息不會報錯.

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時,就大廳釋放.只要還有人,哪怕是一個人也不能釋放大廳.

4.@property修飾符

readonly:只生成getter方法

readwrite:同時生成getter/setter方法,預設情況下不寫就是readwrite

getter:可以給生成的gutter方法起名稱

setter:可以給生成的setter方法起名稱

retain:會自動幫我們生成setter/gettter方法記憶體管理的程式碼

assign:不會替我們生成setter方法的記憶體管理方法,僅僅只是生成普通的gettter/setter方法,預設什麼都不寫就是assign

5.@class

@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 : 用於基本資料型別,相當於MRC中的assign