關於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...