iOS---自動釋放池

來源:互聯網
上載者:User

iOS---自動釋放池
自動釋放池

  • 在 mrc 的代碼中,沒有 weak,只有 assign
  • assign 修飾符號,對對象不做任何操作,只是簡單的記錄地址
  • weak 是 ARC 專有的,如果對象沒有其他任何對象做強引用,會被立即釋放!
  • weak 的效率非常差!
  • assign 會記錄住地址,對象釋放後,地址仍然保留,在 MRC 開發中,野指標錯誤非常頻繁
  • weak 安全性很好!一旦沒有強引用,自動將地址設定為 nil,OC中可以向 nil 發送任何訊息都不會抱錯!

  • autorelease 作用就是延遲釋放,給對象添加延遲釋放的標記

    自動釋放對象 atuorelease自動釋放對象
    • 所有 "autorelease" 的對象,在出了範圍之後,會被自動添加到"最近建立的"自動釋放池中!
    • 在自動釋放池被銷毀或者耗盡的時候,會向池中所有對象發送 release 訊息,釋放池中對象
    • 自動釋放池,在 ARC & MRC 程式中,同樣有效!MRC 下系統變數的測試

      聲明變數

      @property (nonatomic, assign) UIButton *btn;

      向控制器View中添加按鈕:

      // alloc / init - 應該出了範圍才會被釋放    //    self.btn = [[UIButton alloc] init];    self.btn.frame = CGRectMake(40, 40, 100, 100);    self.btn.backgroundColor = [UIColor orangeColor];    [self.view addSubview:self.btn];    NSLog(@"%@", self.view.subviews);    // 類方法建立的 - 是 ‘autorelease’ 的    // 出了範圍,會被添加到自動釋放池中    // 自動釋放池被銷毀前,才釋放對象!    self.btn = [UIButton buttonWithType:UIButtonTypeContactAdd];    [self.view addSubview:self.btn];    NSLog(@"%@", self.view.subviews);    // ARC 上述演練不好使!以 weak 為主!

      運行結果:

      2015-03-25 10:31:20.055 09-自動釋放池[27279:718327] (    "<_UILayoutGuide: 0x7fc5d0d346b0; frame = (0 0; 0 0); hidden = YES; layer = >",    "<_UILayoutGuide: 0x7fc5d0e77950; frame = (0 0; 0 0); hidden = YES; layer = >",    ">")2015-03-25 10:31:20.063 09-自動釋放池[27279:718327] (    "<_UILayoutGuide: 0x7fc5d0d346b0; frame = (0 0; 0 0); hidden = YES; layer = >",    "<_UILayoutGuide: 0x7fc5d0e77950; frame = (0 0; 0 0); hidden = YES; layer = >",    ">",    ">")

      可以看到,無論是alloc還是buttonWithType: 都是可以添加到控制器的View上的,也就意味著,建立出來的button並沒有立刻銷毀

      • assign 聲明的變數,在alloc後,對象並不會立刻釋放,除了範圍才會銷毀,即使是對象銷毀後,assign記錄的地址並不會清除,這就很容易造成野指標錯誤
      • 利用buttonWithType: 建立出來的,也不會立刻釋放,系統類別方法建立出來的對象,是預設autorealease的,出了範圍,會自定添加到自動釋放池中,自動釋放池銷毀前,才會釋放對象,同樣assign聲明的變數會持有該對象的地址,一直不肯放~MRC下自訂對象的自動釋放

        Person.h

        @interface Person : NSObject+ (instancetype)person;@end

        Person.m

        • 注意:這裡沒有添加autorelease
          @implementation Person+ (instancetype)person {    // autorelease 作用就是延遲釋放    // 給對象添加延遲釋放的標記    Person *p = [[Person alloc] init] ;    return p;}- (void)dealloc {    NSLog(@"我去了");    [super dealloc];}@end

          聲明Persion變數:

          @property (nonatomic, assign) Person *p;

          測試Demo:

          - (void)viewDidLoad {    [super viewDidLoad];    // Do any additional setup after loading the view, typically from a nib.    self.p = [Person person];    NSLog(@"%@", self.p);}

          運行結果:

          2015-03-25 10:44:16.652 10-ARC自動釋放[27546:726446] 
          小結:

          在MRC下,如果提供的類方法沒有autorelease,那麼在調用的時候,用assign變數接收,仍然會列印出對象的地址,當然對象並沒有銷毀(dealloc沒有輸出)。

          將類方法帶上 autorelease
          Person *p = [[[Person alloc] init] autorelease];

          列印結果:

          2015-03-25 10:56:04.224 10-ARC自動釋放[27690:732059] 2015-03-25 10:56:04.238 10-ARC自動釋放[27690:732059] 我去了

          可以看到對象被釋放了,說明autorelease給對象添加了延遲釋放的標記,讓對象在自動是釋放池銷毀,或者出了離它最近的自動釋放池範圍的時候,自動釋放。

          ARC中的自動釋放

          變數的聲明:

          @property (nonatomic, weak) Person *p;@property (nonatomic, weak) UIButton *button;

          測試Demo:

          // ARC 中,如果給 weak 做 alloc / init 的設定數值,Xcode 會提示!    self.p = [[Person alloc] init];    // 對於 Xcode 編譯器而言,只要是類方法,就不會提示!    // 如果使用 MRC 開發,所有 返回 instancetype 的類方法,返回的對象都是 autorelease 的!    // 因為沒有強引用,會被立即釋放    self.p = [Person person];    // ARC中之所以為 null,是因為 weak,跟autorelease沒有關係!    NSLog(@"%@", self.p);    // 之所以會這樣是因為蘋果架構的底層是用 MRC 寫的,buttonWithType返回的對象是帶有 autorelease    self.button = [UIButton buttonWithType:UIButtonTypeContactAdd];    NSLog(@"%@", self.button);

          列印結果:

          2015-03-25 11:00:58.756 10-ARC自動釋放[27778:735123] (null)2015-03-25 11:00:58.769 10-ARC自動釋放[27778:735123] >
          小結
          • 如果普通對象的alloc,且對象是weak的,Xcode會自動提示警告,告訴你這個對象,一建立就會被銷毀啦
          • 但是如果你提供了一個類方法,快速產生。即使內部寫的是alloc,Xcode也不會警告你,但是你不能改變一建立就被銷毀的事實。
          • 蘋果自己提供的類方法建立的button,我們用weak接收,卻沒有銷毀,為啥呢,因為蘋果架構的底層是用MRC寫的,buttoWithType:返回的對象都是帶autorelease的,意味著會延遲銷毀,僅僅是被添加到自動釋放池而已,等待著出自動釋放池範圍或者自動釋放池銷毀。而不會立刻銷毀。一道經典面試題

            問題:以下代碼是否有問題?如果有,如何解決?

            for (long i = 0; i < largeNumber; ++i) {        @autoreleasepool {            NSString *str = [NSString stringWithFormat:@"hello - %ld", i];            str = [str uppercaseString];            str = [str stringByAppendingString:@" - world"];        }    }

            答案:如果 largeNumber 非常大,會建立太多自動釋放的對象,有可能會把自動釋放池"撐滿" 提示:經常一次使用者互動,遠遠不止一個 for,在 for 的前後,會有很多的代碼,但是這個 for 會佔用大量的自動釋放池空間

            解決方案

            引入自動釋放池,網路上有兩種解決方案!

             1> 外面加自動釋放池(快):能夠保證for迴圈結束後,內部產生的自動釋放對象,都會被銷毀    需要等到 for 結束後,才會釋放記憶體 2> 裡面加自動釋放池(慢):能夠每一次 for 都釋放產生的自動釋放對象! 提問:那種方式效率高!速度差不多!大多數測試內部比外部外! 如果面試中問道:要說裡面的略快,“親測”!!! 提示:在日常工作中!有的時候,真的會出現代碼記憶體飆升的情況!要知道解決辦法!

            設定largeNumner的數值:

            long largeNumber = 5 * 1000 * 1000;

            測試Demo:

            NSLog(@"內部 start");    CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();    for (long i = 0; i < largeNumber; ++i) {        @autoreleasepool {            NSString *str = [NSString stringWithFormat:@"hello - %ld", i];            str = [str uppercaseString];            str = [str stringByAppendingString:@" - world"];        }    }    NSLog(@"end - %f", CFAbsoluteTimeGetCurrent() - start);    [self answer1];

            answer1方法:

             NSLog(@"外面 start");    CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();    @autoreleasepool {        for (long i = 0; i < largeNumber; ++i) {            NSString *str = [NSString stringWithFormat:@"hello - %ld", i];            str = [str uppercaseString];            str = [str stringByAppendingString:@" - world"];        }    }    NSLog(@"end - %f", CFAbsoluteTimeGetCurrent() - start);

            測試結果:

            2015-03-25 11:18:50.663 12-自動釋放池的面試題[28015:743360] 內部 start2015-03-25 11:19:03.996 12-自動釋放池的面試題[28015:743360] end - 13.3323712015-03-25 11:19:03.996 12-自動釋放池的面試題[28015:743360] 外面 start2015-03-25 11:19:18.227 12-自動釋放池的面試題[28015:743360] end - 14.230752

            由測試結果可以知道,對於500w次迴圈,內部、外部添加autorelease,速度其實差不多,內部略微快一點,但這是取決於編譯器。 但是,在外部添加autorelease會佔用極大的記憶體(注意,這裡跟不加autorelease不一樣,不加autorelease開闢的記憶體是不會釋放的)。 開發中,通常在內部添加。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.