oc007 記憶體管理

2021-07-04 00:15:16 字數 3436 閱讀 7743

➢ 每個oc物件都有自己的引用計數器,是乙個整數,表示「物件被引用的次數」,即有多少人正在使用這個oc物件

➢ 每個oc物件內部專門有4個位元組的儲存空間來儲存引用計數器

引用計數器的作用

➢ 當使用alloc、new或者copy建立乙個新物件時,新物件的引用計數器預設就是1

➢ 當乙個物件的引用計數器值為0時,物件占用的記憶體就會被系統**。換句話說,如果物件的計數器不為0,那麼在整個程式執行過程,它占用的記憶體就不可能被**,除非整個程式已經退出

引用計數器的操作

➢ 給物件傳送一條retain訊息,可以使引用計數器值+1(retain方法返回物件本身)

➢ 給物件傳送一條release訊息,可以使引用計數器值-1

➢ 可以給物件傳送retaincount訊息獲得當前的引用計數器值

物件的銷毀

➢ 當乙個物件的引用計數器值為0時,那麼它將被銷毀,其占用的記憶體被系統**

➢ 當乙個物件被銷毀時,系統會自動向物件傳送一條dealloc訊息

➢ 一般會重寫dealloc方法,在這裡釋放相關資源,dealloc就像物件的遺言

➢ 一旦重寫了dealloc方法,就必須呼叫[super dealloc],並且放在最後面呼叫

➢ 不要直接呼叫dealloc方法

➢ 一旦物件被**了,它占用的記憶體就不再可用,堅持使用會導致程式崩潰(野指標錯誤)

2.記憶體管理原則

誰建立,誰release

➢ 如果你通過alloc、new或[mutable]copy來建立乙個物件,那麼你必須呼叫release或autorelease

➢ 換句話說,不是你建立的,就不用你去[auto]release

誰retain,誰release

➢ 只要你呼叫了retain,無論這個物件是如何生成的,你都要呼叫release

總結 ➢ 有始有終,有加就有減

➢ 曾經讓物件的計數器+1,就必須在最後讓物件計數器-1

dealloc方法的實現

4、 @property引數

1. 控制set方法的記憶體管理

➢ retain : release舊值,retain新值(用於oc物件)

➢ assign : 直接賦值,不做任何記憶體管理(預設,用於非oc物件型別)

➢ copy : release舊值,copy新值(一般用於nsstring *)

控制需不需生成set方法

➢ readwrite :同時生成set方法和get方法(預設)

➢ readonly :只會生成get方法

多執行緒管理

➢ atomic :效能低(預設)

➢ nonatomic :效能高

控制set方法和get方法的名稱

➢ setter : 設定set方法的名稱,一定有個冒號:

➢ getter : 設定get方法的名稱

5、 迴圈引用

1. @class

➢ 使用場景

對於迴圈依賴關係來說,比方a類引用b類,同時b類也引用a類

這種**編譯會報錯。當使用@class在兩個類相互宣告,就不會出現編譯報錯

➢ 用法概括

使用 @class 類名; 就可以引用乙個類,說明一下它是乙個類

➢ 和#import的區別

 #import方式會包含被引用類的所有資訊,包括被引用類的變數和方法;@class方式只是告訴編譯器在a.h檔案中 b *b 只是類的宣告,具體這個類裡有什麼資訊,這裡不需要知道,等實現檔案中真正要用到時,才會真正去檢視b類中資訊

 如果有上百個頭檔案都#import了同乙個檔案,或者這些檔案依次被#improt,那麼一旦最開始的標頭檔案稍有改動,後面引用到這個檔案的所有類都需要重新編譯一遍,這樣的效率也是可想而知的,而相對來 講,使用@class方式就不會出現這種問題了

 在.m實現檔案中,如果需要引用到被引用類的實體變數或者方法時,還需要使用#import方式引入被引用類

迴圈retain

➢ 比如a物件retain了b物件,b物件retain了a物件

➢ 這樣會導致a物件和b物件永遠無法釋放

解決方案

➢ 當兩端互相引用時,應該一端用retain、一端用assign

6、 autorelease

1. autorelease

➢ 給某個物件傳送一條autorelease訊息時,就會將這個物件加到乙個自動釋放池中

➢ 當自動釋放池銷毀時,會給池子裡面的所有物件傳送一條release訊息

➢ 呼叫autorelease方法時並不會改變物件的計數器,並且會返回物件本身

➢ autorelease實際上只是把對release的呼叫延遲了,對於每一次autorelease,系統只是把該物件放入了當前的autorelease pool中,當該pool被釋放時,該pool中的所有物件會被呼叫release

自動釋放池的建立

➢ ios 5.0後

@autoreleasepool

➢ ios 5.0前

nsautoreleasepool *pool = [[nsautoreleasepool alloc] init];

// …..

[pool release]; // 或[pool drain];

➢ 在程式執行過程中,可以建立多個自動釋放池,它們是以棧的形式存在記憶體中

➢ oc物件只需要傳送一條autorelease訊息,就會把這個物件新增到最近的自動釋放池中(棧頂的釋放池)

應用例項

➢ 跟release的對比

 以前:

book *book = [[book alloc] init];

[book release];

 現在:

book *book = [[[book alloc] init] autorelease];

// 不要再呼叫[book release];

➢ 一般可以為類新增乙個快速建立物件的類方法

+ (id)book

外界呼叫[book book]時,根本不用考慮在什麼時候釋放返回的book物件

規律 ➢ 一般來說,除了alloc、new或copy之外的方法建立的物件都被宣告了autorelease

➢ 比如下面的物件都已經是autorelease的,不需要再release

nsnumber *n = [nsnumber numberwithint:100];

nsstring *s = [nsstring stringwithformat:@」jack」];

nsstring *s2 = @」rose」;

Oc 記憶體管理

1 對你自己擁有的物件負責,你只能釋放你擁有的物件 2 凡是你通過 retain alloc copy等手段獲得了所有者的物件,都必須在你不使用的時候來呼叫release autorelease等手段來釋放對他的所有權 3 在一定的 段內,對同乙個物件所作的copy alloc retain的操作次...

OC記憶體管理

1.記憶體管理原則 如果對乙個物件使用了alloc mutable copy retain,那麼你必須使用相應的release或者autorelease。2.管理範圍 任何繼承了nsobject 的物件,對其他基本資料型別 int char float double struct enum等 無效 ...

OC 記憶體管理

管理範圍 任何繼承nsobject的物件,對其他的基本資料型別無效。判斷物件要不要 的唯一依據就是計數器是否為0,若不為0則存在。所以對記憶體的管理就是對計數器的管理 1 retain 計數器 1,會返回物件本身 2 release 計數器 1 沒有返回值 3 retaincount 獲取當前的計數...