1. 什麼是記憶體管理
➢ 管理範圍:任何繼承了nsobject的物件,對其他基本資料型別(int、char、float、double、struct、enum等)無效。
2. 物件的基本結構
➢ 每個oc物件都有自己的引用計數器,是乙個整數,表示「物件被引用的次數」,即有多少人正在使用這個oc物件
➢ 每個oc物件內部專門有4個位元組的儲存空間來儲存引用計數器
3. 引用計數器的作用
➢ 當使用alloc、new或者copy建立乙個新物件時,新物件的引用計數器預設就是1。
➢ 當乙個物件的引用計數器值為0時,物件占用的記憶體就會被系統**。換句話說,如果物件的計數器不為0,那麼在整個程式執行過程,它占用的記憶體就不可能被**,除非整個程式已經退出。
➢當計數器為0時則不能呼叫release或者retain count,否則引起crash。
4. 引用計數器的操作
➢ 給物件傳送一條retain訊息,可以使引用計數器值+1(retain方法返回物件本身)
➢ 給物件傳送一條release訊息,可以使引用計數器值-1
➢ 可以給物件傳送retaincount訊息獲得當前物件的引用計數器值
5. 物件的銷毀
➢ 當乙個物件的引用計數器值為0時,那麼它將被銷毀,其占用的記憶體被系統**
➢ 當乙個物件被銷毀時,系統會自動向物件傳送一條dealloc訊息。
➢ 一般會重寫dealloc方法,在這裡釋放相關資源,dealloc就像物件的遺言。
➢ 一旦重寫了dealloc方法,就必須呼叫[super dealloc],並且放在最後面呼叫。
➢ 不要直接呼叫dealloc方法。
➢ 一旦物件被**了,它占用的記憶體就不再可用,堅持使用會導致程式崩潰(野指標錯誤)。
誰建立,誰release
➢ 如果你通過alloc、new或[mutable]copy來建立乙個物件,那麼你必須呼叫release或autorelease
➢ 換句話說,不是你建立的,就不用你去[auto]release
誰retain,誰release
➢ 只要你呼叫了retain,無論這個物件是如何生成的,你都要呼叫release
總結
➢ 有始有終,有加就有減
➢ 曾經讓物件的計數器+1,就必須在最後讓物件計數器-1
set方法記憶體管理
比如有個book *_book
1. set方法的實現
- (void)setbook:(book *)book
} 2. dealloc方法的實現
- (void)dealloc
@property引數
1. 控制set方法的記憶體管理
➢ retain : release舊值,retain新值(用於oc物件)
➢ assign : 直接賦值,不做任何記憶體管理(預設,用於非oc物件型別)
➢ copy : release舊值,copy新值(一般用於nsstring *)
2. 控制需不需生成set方法
➢ readwrite :同時生成set方法和get方法(預設)
➢ readonly :只會生成get方法
3. 多執行緒管理
➢ atomic :效能低(預設)
➢ nonatomic :效能高
4. 控制set方法和get方法的名稱
➢ setter : 設定set方法的名稱,一定有個冒號:
➢ getter : 設定get方法的名稱
迴圈引用
1. @class
➢ 使用場景 對於迴圈依賴關係來說,比方a類引用b類,同時b類也引用a類 這種**編譯會報錯。當使用@class在兩個類相互宣告,就不會出現編譯報錯
➢ 用法概括 使用
@class 類名; 就可以引用乙個類,說明一下它是乙個類
➢ 和#import的區別
#import方式會包含被引用類的所有資訊,包括被引用類的變數和方法;@class方式只是告訴編譯器在a.h檔案中 b *b 只是類的宣告,具體這個類裡有什麼資訊,這裡不需要知道,等實現檔案中真正要用到時,才會真正去檢視b類中資訊
如果有上百個頭檔案都#import了同乙個檔案,或者這些檔案依次被#improt,那麼一旦最開始的標頭檔案稍有改動,後面引用到這個檔案的所有類都需要重新編譯一遍,這樣的效率也是可想而知的,而相對來 講,使用@class方式就不會出現這種問題了
在.m實現檔案中,如果需要引用到被引用類的實體變數或者方法時,還需要使用#import方式引入被引用類
2. 迴圈retain
➢ 比如a物件retain了b物件,b物件retain了a物件
➢ 這樣會導致a物件和b物件永遠無法釋放
3. 解決方案
➢ 當兩端互相引用時,應該一端用retain、一端用assign
autorelease
1. autorelease
➢ 給某個物件傳送一條autorelease訊息時,就會將這個物件加到乙個自動釋放池中。
➢ 當自動釋放池銷毀時,會給池子裡面的所有物件傳送一條release訊息。
➢ 呼叫autorelease方法時並不會改變物件的計數器,並且會返回物件本身。
➢ autorelease實際上只是把對release的呼叫延遲了,對於每一次autorelease,系統只是把該物件放入了當前的。autorelease pool中,當該pool被釋放時,該pool中的所有物件會被呼叫release。
2. 自動釋放池的建立
➢ ios 5.0後
@autoreleasepool
➢ ios 5.0前
nsautoreleasepool *pool = [[nsautoreleasepool alloc] init];
// .....
[pool release];
// 或[pool drain];
➢ 在程式執行過程中,可以建立多個自動釋放池,它們是以棧的形式存在記憶體中
➢ oc物件只需要傳送一條autorelease訊息,就會把這個物件新增到最近的自動釋放池中(棧頂的釋放池)
3. 應用例項
➢ 跟release的對比
以前: book *book = [[book alloc] init];
[book release];
現在: book *book = [[[book alloc] init] autorelease];
// 不要再呼叫[book release];
➢ 一般可以為類新增乙個快速建立物件的類方法
+ (id)book
外界呼叫[book book]時,根本不用考慮在什麼時候釋放返回的book物件
4. 規律
➢ 一般來說,除了alloc、new或copy之外的方法建立的物件都被宣告了autorelease。
➢ 比如下面的物件都已經是autorelease的,不需要再release。
nsnumber *n = [nsnumber numberwithint:100];
nsstring *s = [nsstring stringwithformat:@"jack"];
nsstring *s2 = @"rose";
ios記憶體管理
引用計數 每個物件有乙個與之相關的整數,稱作 引用計數器 或者 保留計數器 當某段 需要訪問乙個物件時,該段 會將物件的保留計數器 1,表示需要訪問這個物件 當結束對該物件的訪問時,保留計數器 1,表示它不在訪問該物件 當保留計數器為0時,物件被銷毀,所佔記憶體被系統收回。當使用new retain...
iOS記憶體管理
前提 1 以下是針對cocoa物件,不包括core foundation 2 cocoa物件都是用引用計數來跟蹤物件的記憶體使用情況的。3 在子類裡面父類先初始化和後釋放的原則。自己想下為什麼 棧空間和堆空間的區別。我們說的記憶體管理都是基於堆空間的,因為函式內的棧空間是由編譯器自己控制的。關於co...
IOS 記憶體管理
範圍 任何繼承了nsobject的物件,對基本資料型別無效 原理 每個物件內部都儲存了乙個與之相關聯的整數,稱為引用計數器 當使用alloc new或者copy建立乙個物件時,物件的引用計數器被設定為1 給物件傳送一條retain訊息,可以使引用計數器值 1 給物件傳送一條release訊息,可以使...