你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> 詳解關於iOS內存管理的規則思考

詳解關於iOS內存管理的規則思考

編輯:IOS開發綜合

關於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_obj 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問題

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved