weakSelf 和 strongSelf的區別和用處


block會copy要在block中使用的實變量,而copy會是變量的retainCount + 1,如若在不注意很容易造成循環引用。而所謂的循環引用的本質就是,兩個對象相互引用,從而造成對象不能正常的dealloc。所以解決的辦法就是讓引用的一方是weak的,這樣就使得相互引用的閉環被打破,能夠正常的dealloc了。

 

1)weakSelf的使用:

Apple 官方的建議是,傳進 Block 之前,把 ‘self’ 轉換成 weak automatic 的變量,這樣在 Block 中就不會出現對 self 的強引用。 

上圖的代碼中,backgroundTaskId是當前這個類的一個屬性,在backgroundTaskId初始化的這個方法中,有一個block回調,在這個block的實現中訪問需要訪問Self,為了避免造成循環引用,此處給當前的Self取了個別名,並用__weak來修飾,目的是告訴編譯器,此處是弱引用,不要retain 當前的這個類,也就是所謂的self。

2)為什么會出現strongSelf?

Apple 官方文檔有講到,如果在 Block 執行完成之前,self 被釋放了,weakSelf 也會變為 nil。

clang給出的實例代碼:

 

    __weak __typeof__(self) weakSelf = self;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        [weakSelf doSomething];

    });

 clang 的文檔表示,在 doSomething 內,weakSelf 不會被釋放。但,下面的情況除外:

    __weak __typeof__(self) weakSelf = self;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        [weakSelf doSomething];

        [weakSelf doOtherThing];

    });

 

 在 doSomething 中,weakSelf 不會變成 nil,不過在 doSomething 執行完成,調用第二個方法 doOtherThing 的時候,weakSelf 有可能被釋放,

 於是,strongSelf 就派上用場了:

    __weak __typeof__(self) weakSelf = self;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        __strong __typeof(self) strongSelf = weakSelf;

        [strongSelf doSomething];

        [strongSelf doOtherThing];

    });

   __strong 確保strongSelf在block中不會被釋放。

 

所以就能理解SDWebImage中的那段代碼,block在實現的過程中會對wself進行一次強引用,是為了防止在block還未執行完畢,wself在其他線程中被釋放,使得wself為nil。

 

 簡單的做個小結:

 1、在使用block時,如果block內部需要訪問self的方法、屬性、或者實例變量應當使用weakSelf

 2、如果在block內需要多次訪問self,則需要使用strongSelf

 3、如果在block內部存在多線程環境訪問self,則需要使用strongSelf

 4、block本身不存在多線程之分,block執行是否是多線程,取決於當前的持有者是否是以多線程的方式來調用它。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM