詳解關於iOS記憶體管理的規則思考

2022-09-26 10:33:15 字數 4299 閱讀 2551

關於ios記憶體管理的規則思考

自己生成的生成的物件,自己持有。

非自己生成的物件,自己也能持有。

不在需要自己持有的物件時釋放。

非自己持有的物件無法釋放。

注:這裡的自己是物件使用的環境,理解為程式設計人員本身也沒有錯

物件操作和objective-c方法對應

物件操作

objectivew-c方法

生成並持有物件

alloc/copy/mutablecopy/new或以此開頭的方法

持有物件

retain

釋放物件

release

廢棄物件

dealloc

自己生成的物件,自己持有

//自己生成並持有物件

id obj1 = [[nsobject alloc] init];

id obj2 = [nsobject new];

id obj3 = [obj2 copy];

copy方法基於nscopying方法約定,實現類中的copywithzone:

mutablecopy方法基於nsmutablecopying方法約定,實現類中的mutablecopywithzone:

非自己生成的物件,自己也能持有

用alloc/new/copy/mutablecopy以外的方法取得的物件,自己不是該物件的持有者。

//取的非自己生成並持有的物件,

//取得物件的存在,但自己不持有物件。

id obj = [nsmutablearray array];

id obj2 = [nsdictionary dictionary];

//自己持有物件

[obj retain];

[obj2 retain];

注:這裡有點不好理解,我們先來看一段**:

//取的非自己生成並持有的物件,

//取得物件的存在,但自己不持有物件。

id unretain_obj = [nsmutablearray array];

nslog(@"unretain_obj retain count = %lu", (unsigned long)[unretain_obj retaincount]);

//呼叫 release

[unretain_obj release];

上述**,我們列印結果是:

2016-12-21 15:32:04.485 acm[65216:852108] unretain_obj retain count = 1

隨後呼叫release方法會導致程式崩潰!

按照引用計數來說,這時unretain_obj是可以被執行一次release方法的。但是為什麼我們直接呼叫會導致程式崩潰。

我們會想最開始提到的四條思想程式設計客棧之一:

無法釋放非自己持有的物件

這樣我們就很好理解了。雖然列印出unretain_obj的retaincount 為 1 但是不能說明是因為它引用了物件。它只是單純的獲取到了物件的存在而已。

程式設計客棧那麼我們會產生乙個問題。那麼這個物件是誰在持有??

我們先做乙個猜測:

因為[nsmutablearray array]是乙個工廠方法,在array肯定是要生成乙個nsmutablearray例項物件。這時也必然會有乙個指標引用它然後返回這個物件。so。。。

先想到這裡,後邊我們再去印證

我們再來看一段**:

//取的非自己生成並持有的物件,

//取得物件的存在,但自己不持有物件。

id unretain_obj = [nsmutablearray array];

nslog(@"unretain_obj retain count = %lu", (unsigned long)[unretain_obj retaincount]);

//自己持有物件

[unretain_obj retain];

nslog(@"unretain_obj retain count = %lu", (unsigned long)[unretain_obj retaincount]);

//釋放自己持有的物件

[unretain_obj release];

nslog(@"unretain_obj retain count = %lu", (unsigned long)[unretain_objwww.cppcns.com retaincount]);

列印結果

2016-12-21 15:40:20.774 acm[65682:861135] unretain_obj retain count = 1

2016-12-21 15:40:20.774 acm[65682:861135] unretain_obj retain count = 2

2016-12-21 15:40:25.254 acm[65682:861135] unretain_obj retain count = 1

並且程式也不會崩潰。

著也印證了我們上邊的想法。

因為通過retain方法,非自己生成的物件跟用alloc/new/copy/mutablecopy方法生成並持有的物件一樣,成了自己所持有的

不在需要自己持有的物件時釋放

通過上邊的例子我們知道,自己持有的物件在釋放時呼叫release方法,eg:

//自己生成並持有物件

id release_obj = [[nsobject alloc] init];

//將自己持有的物件釋放

[release_obj release];

/* * 釋放物件

* 指向物件的指標依然被保留在變數release_obj 中,你依然可以呼叫它。

* 但是物件一經釋放絕對不可訪問,否則會造成程式崩潰。

* 出現exc_bad_access crash問題

*/我們自己實現乙個方法,返回乙個方法呼叫著也可以持有的物件,即alloc的作用

- (id)allocobject {

//自己生成並持有物件

id obj = [[nsobject alloc] init];

//原封不動的返回乙個由alloc方法生成的物件

return obj;

注:方法名符合 生程式設計客棧成並持有物件  alloc/copy/mutablecopy/new或以此開頭的方法 規則

我們自己實現乙個方法,返回乙個誰也不持有的物件,只是取得物件的存在

- (id)object {

//自己生成並持有物件

id obj = [[nsobject alloc] init];

//呼叫autorelease方法 取得物件的存在,但自己不持有物件。

[obj autorelease];

return obj;

autorelease方法可以取得物件的存在,但自己不持有物件。使物件在超出指定的生存範圍時能夠自動的並正確的釋放(呼叫release方法)

autorelease和release方法的區別

autorelease:

release:

autorelease的詳細解說我們後邊介紹。

我們也可以通過呼叫retain方法來使 autorelease方法的來的物件自己持有eg:

//獲取物件的存在,自己不持有

id unretain_obj = [nsmutablearray array];

//持有物件

[unretain_obj retain];

無法釋放非自己持有的物件

自己已經釋放了還繼續釋放

//自己生成並持有物件

id release_obj = [[nsobject alloc] init];

//將自己持有的物件釋放

[release_obj release];

//釋放已經釋放的物件

[release_obj release];

/** 釋放物件

* 指向物件的指標依然被保留在變數release_obj 中,你依然可以呼叫它。

* 但是物件一經釋放絕對不可訪問,否則會造成程式崩潰。

* 出現exc_bad_access crash問題

*/只獲取了物件的存在,試圖釋放物件

//取的非自己生成並持有的物件,

//取得物件的存在,但自己不持有物件。

id unretain_obj = [nsmutablearray array];

//釋放自己不持有的物件

[unretain_obj release];

程式崩潰,報exc_bad_access crash問題

本文標題: 詳解關於ios記憶體管理的規則思考

本文位址: /ruanjian/ios/174584.html

IOS記憶體管理規則

1 釋放物件,可以釋放其所佔的記憶體,規則是 不再使用建立或者保持的物件時,就釋放它們。2 傳送一條release小心不一定銷毀物件,只有引用計數變為0時,才銷毀這個物件。系統向物件傳送一條dealloc訊息來釋放它所佔的記憶體。3 自動釋放池在釋放池本身的時候自動釋放池中的物件。系統向每個物件傳送...

iOS 記憶體管理詳解

在arc下主要有以下幾個關鍵字 1.關鍵字 strong 預設值,表示只要有強引用指標指向該變數,則該變數會一直存在。2.關鍵字 weak 弱引用,表示若沒有任何強引用指標指向該變數,會自動將變數的值置為空,即nil狀態。3.關鍵字 autoreleasing 用於標示自動釋放的變數 4.關鍵字 u...

iOS關於block的記憶體管理

person person person alloc init int a 20 person.age nsstring stringwithformat d a void myblock2 無引數無返回值的 a 呼叫block myblock 我們在block內部呼叫乙個區域性變數,當我們在呼叫b...