OC記憶體管理三

2021-07-06 06:13:24 字數 4618 閱讀 2979

一、 迴圈retain的場景

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

• 迴圈retain的弊端

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

• 迴圈retain的解決方案

當兩端互相引用時,應該一端用retain、一端用assign(weak)

二、@class

1、@class的使用

在.h檔案中使用@class引用乙個類

在.m檔案中使用#import包含這個類的.h檔案

@class 和 #import 的區別

這兩種的方式的區別在於:

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

2)使用@class方式由於只需要只要被引用類(b類)的名稱就可以了,而在實現類由於要用到被 引用類中的實體變數和方法,所以需要使用#import來包含被引用類的標頭檔案;

3)通過上面2點也很容易知道在編譯效率上,如果有上百個頭檔案都#import了同一 個檔案,或 者這些檔案依次被#improt(a->b, b->c,c->d…),一旦最開始的標頭檔案稍有改動,後面引用到這 個檔案的所有類都需要重新編譯一遍,這樣的效率也是可想而知的,而相對來 講,使用@class方 式就不會出現這種問題了;

所以:我們實際開發中盡量在.h標頭檔案中使用@class

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

當程式執行時,#import編譯會報錯,

三、nsstring的記憶體管理問題

1—> nsstring *str = [[nsstring alloc] initwithstring:@」abc」];

2—> str = @」123」;

3—> [str release];

4—> nslog(@」%@」,str);

首先,咱們先對這段**進行分析。

第一句 宣告了乙個nsstring型別的例項 str, 並將其初始化init後賦值為@」abc」 第二行,將str的指標指向了乙個常量@」123」。 理論上講在第一行初始化的@」abc」沒有任何任何 指標指向了。 所以造成了記憶體洩露

然後第三行, 將str的引用計數-1

第四行輸出str的值 為123.

首先回答為什麼不會崩潰, 因為第三行的release 實際上是release了乙個常量@」123」 而作為 常量,其預設的引用計數值是很大的(100k+)

nslog(@」retaincount = %tu」,[@」123」 retaincount]); 最終的輸出值會是乙個很大很大的數。 所以單單乙個release是不會將其釋放掉的。

然後再回答這樣會不會造成記憶體洩露。

其實…………理論上講 會! 但是實際上,objective-c對nsstring型別有特殊照顧。所有的nsstring的引用計數器預設初始值 都會非常非常大。

三、autorelease自動釋放池基本使用

• autorelease方法的基本作用

• 1、給物件傳送一條autorelease訊息, 會將物件放到乙個自動釋放池中

• 2、當自動釋放池被銷毀時,會對池子裡面的所有物件做一次release操作

• 3、會返回物件本身

• 4、呼叫完autorelease方法後,物件的計數器不變

• autorelease的好處

• 不用再關心物件釋放的時間

• 不用再關心什麼時候呼叫release

• autorelease的使用注意

• 占用記憶體較大的物件不要隨便使用autorelease

• 占用記憶體較小的物件使用autorelease,沒有太大影響

• 自動釋放池:

• 在ios程式執行過程中,會建立無數個池子。這些池子都是以棧結構存在(先進後出)

• 當乙個物件呼叫autorelease方法時,會將這個物件放到棧頂的釋放池

• 自動釋放池的建立方式】

• ios 5.0前

nsautoreleasepool *pool = [[nsautoreleasepool alloc] init]; [pool release]; // [pool drain];

• ios 5.0 開始

@autoreleasepool

autoreleasepool 的 實現

autorelease

是一種支援引用計數的記憶體管理方式 它可以暫時的儲存某個物件(object),然後在記憶體池自己的排乾(drain)的時候對其中的每個 物件傳送release訊息 注意,這裡只是傳送release訊息,如果當時的引用計數(reference-counted)依然不為0,則該 物件依然不會被釋放。可以用該方法來儲存某個物件,也要注意儲存之後要釋放該物件。

2、為什麼會有autorelease?

oc的記憶體管理機制中比較重要的一條規律是:誰申請,誰釋放 考慮這種情況,如果乙個方法需要返回乙個新建的物件,該物件何時釋放? 方法內部是不會寫release來釋放物件的,因為這樣做會將物件立即釋放而返回乙個空物件;呼叫 者也不會主動釋放該物件的,因為呼叫者遵循「誰申請,誰釋放」的原則。那麼這個時候,就發 生了記憶體洩露。

不使用autorelease存在的問題

針對這種情況,objective-c的設計了autorelease,既能確保物件能正確釋放,又能返回有效的 物件。

3、autorelease是什麼原理?

autorelease實際上只是把對release的呼叫延遲了,對於每乙個autorelease,系統只是把該 object放入了當 前的autorelease pool中,當該pool被釋放時,該pool中的所有object會被呼叫 release。

4、autorelease何時釋放?

對於autorelease pool本身,會在如下兩個條件發生時候被釋放(詳細資訊請參見第5條) 1)手動釋放autorelease pool

2)runloop結束後自動釋放

對於autorelease pool內部的物件

在引用計數的retain == 0的時候釋放。release和autorelease pool 的 drain都會觸發retain– 事件。

5、autorelease釋放的具體原理是什麼?

要搞懂具體原理,則要先要搞清楚autorelease何時會建立。 我們的程式在main()呼叫的時候會自動呼叫乙個autorelease,然後在每乙個runloop, 系統會隱 式建立乙個autorelease pool,這樣所有的release pool會構成乙個象callstack一樣的乙個棧式 結構,在每乙個runloop結束時,當前棧頂的 autorelease pool(main()裡的autorelease)會被 銷毀,這樣這個pool裡的每個object會被release。

可以把autorelease pool理解成乙個類似父類與子類的關係,main()建立了父類,每個runloop自 動生成的或者開發者自定義的autorelease pool都會成為該父類的子類。當父類被釋放的時候, 沒有被釋放的子類也會被釋放,這樣所有子類中的物件也會收到release訊息。 那什麼是乙個runloop呢? 乙個ui事件,timer call, delegate call, 乙個滑鼠事件,鍵盤按 下(mac osx),或者iphone上的觸控事件,非同步http連線下後當接收完資料時,都會是乙個新的 runloop。 一般來說,訊息迴圈執行一次是毫秒級甚至微秒級的,因此autorelease的效率仍然是非常高的, 確實是乙個巧妙的設計。

autorelease的常見錯誤

• alloc之後呼叫了autorelease,又呼叫release

person *p = [[[person alloc] init] autorelease];

[p release];

• 連續呼叫多次autorelease

person *p = [[[[person alloc] init] autorelease] autorelease];

autorelease和release使用對比

• 使用release

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

[book release];

• 使用autorelease

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

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

autorelease的應用場合

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

+ (id)book

外界呼叫[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 獲取當前的計數...