iOS夯實:ARC時代的內存管理

iOS夯實:ARC時代的內存管理

文章轉自 ARC時代的內存管理

什麼是ARC

Automatic Reference Counting (ARC) is a compiler feature that provides automatic memory management of Objective-C objects. Rather than having to think about retain and release operations [^1]html

[^1]: Transitioning to ARC Release Notesios

ARC提供是一個編譯器的特性,幫助咱們在編譯的時候自動插入管理引用計數的代碼。
最重要的是咱們要認識到ARC的本質仍然是經過引用計數來管理內存。所以有時候若是咱們操做不當,仍然會有內存泄露的危險。下面就總結一下ARC時代可能出現內存泄露的場景。git

內存泄露類型

  1. 循環引用github

    基於引用計數的內存管理機制沒法繞過的一個問題即是循環引用(retain cycle)
    (Python一樣也採用了基於引用計數的內存管理,可是它採用了另外的機制來清除引用循環致使的內存泄露,而OC和Swift須要咱們本身來處理這樣的問題[^2])app

    • 對象之間的循環引用:使用弱引用避免
    • block與對象之間的循環引用:

    會致使Block與對象之間的循環引用的狀況有:ide

    self.myBlock = ^{ self.someProperty = XXX; };  

    對於這種Block與Self直接循環引用的狀況,編譯器會給出提示。工具

    可是對於有多個對象參與的狀況,編譯器便無能爲力了,所以涉及到block內使用到self的狀況,咱們須要很是謹慎。(推薦涉及到self的狀況,若是本身不是很是清楚對象引用關係,統一使用解決方法處理)this

    someObject.someBlock = ^{ self.someProperty = XXX; }; //尚未循環引用 self.someObjectWithABlock = someObject; // 致使循環引用,且編譯器不會提醒

    解決方案:spa

    __weak SomeObjectClass *weakSelf = self;
    
    SomeBlockType someBlock = ^{
        SomeObjectClass *strongSelf = weakSelf;
        if (strongSelf == nil) {
        // The original self doesn't exist anymore.
        // Ignore, notify or otherwise handle this case.
        }
        [strongSelf someMethod];
    };

    咱們還有一種更簡便的方法來進行處理,實際原理與上面是同樣的,但簡化後的指令更易用。code

    @weakify(self)
    [self.context performBlock:^{ // Analog to strongSelf in previous code snippet. @strongify(self) // You can just reference self as you normally would. Hurray. NSError *error; [self.context save:&error]; // Do something }];

    你能夠在這裏找到@weakify,@strongify工具:MyTools_iOS

[^2]: How does Python deal with retain cycles?

    1. NSTimer

      通常狀況下在action/target模式裏 target通常都是被weak引用,除了NSTimer。

      + (NSTimer *)timerWithTimeInterval:(NSTimeInterval)seconds target:(id)target selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)repeats

      在官方文檔中:

      target
      The object to which to send the message specified by aSelector when the timer fires. The timer maintains a strong reference to this object until it (the timer) is invalidated.

      Timer Programming Topics :

      A timer maintains a strong reference to its target. This means that as long as a timer remains valid, its target will not be deallocated. As a corollary, this means that it does not make sense for a timer’s target to try to invalidate the timer in its dealloc method—the dealloc method will not be invoked as long as the timer is valid.

      舉一個例子,一個Timer的Target是ViewController.

      這個時候,若是咱們是在dealloc方法裏讓timer invalidate,就會形成內存泄露.

      事實上,timer是永遠不會被invalidate.由於此時VC的引用計數永遠不會爲零。由於Timer強引用了VC。而由於VC的引用計數不爲零,dealloc永遠也不會被執行,因此Timer永遠持有了VC.

      所以咱們須要注意在什麼地方invalidate計時器,咱們能夠在viewWillDisappear裏面作這樣的工做。

相關文章
相關標籤/搜索