__weak typeof(self) wself = self分析

首先我們要知道:在block內(nèi)部引用的對(duì)象,系統(tǒng)會(huì)自動(dòng)給它的引用計(jì)數(shù)器+1;然后在block執(zhí)行完畢后,才會(huì)release掉這個(gè)引用;

我們?cè)趧倢W(xué)會(huì)使用block的時(shí)候,在block內(nèi)部使用當(dāng)前對(duì)象的屬性時(shí),一般就直接引用了self關(guān)鍵字;
如果當(dāng)前block的生命周期,是在self這個(gè)對(duì)象的生命周期內(nèi)的,那么,直接使用self是不會(huì)產(chǎn)生什么問題的。

比如下面的代碼:

  obj2.block: ^ (void) {
    [self doSomethingWithObj:self.obj1];
  }

我們來分析下幾種情況:

  • 情況1:obj2 的生命周期比self要短
    也就是,obj2執(zhí)行完畢了這個(gè)block,而且,obj2已經(jīng)被釋放了,self仍然存在,這時(shí),上面的代碼是沒有任何問題的。
    因?yàn)榧词?,在block中,對(duì)self又引用計(jì)數(shù)了2次(一次self引用一次),引用計(jì)數(shù)+2,但是當(dāng)block執(zhí)行完畢后,計(jì)數(shù)器又會(huì)自動(dòng)-2.

  • 情況2:obj2生命周期比self要長
    即:obj2的block還未執(zhí)行完畢,我們的需求就要釋放掉self這個(gè)對(duì)象了。
    顯然,上面的代碼無法釋放,即使在block外部,self對(duì)象的引用已經(jīng)沒有對(duì)象了,但是在block中,self的引用計(jì)數(shù)仍然有2個(gè),self對(duì)象是無法被釋放的。

為了解決 情況2 的需求,我們要在block中訪問self弱引用,即:

__weak typeof(self) wself = self;
obj2.block: ^ (void) {
  if (wself) { // 要判斷self是否存在,存在才能執(zhí)行它的方法
    [wself doSomethingWithObj:wself.obj1];
  }
}

如上面,使用了弱引用,就不會(huì)影響我們?cè)谕獠繉?duì)self進(jìn)行釋放了。
但是,既然self隨時(shí)可能釋放,我們?cè)赽lock中如果想要使用self的方法,就要先判斷self到底有沒有被釋放。

  • 情況3:對(duì)情況2的補(bǔ)充
    直接上代碼:

    __weak typeof(self) wself = self;
    obj2.block: ^ (void) {
      if (wself) { // 要判斷self是否存在,存在才能執(zhí)行它的方法
        [wself doSomething];
        // ... n秒后
        [wself doOtherthing];
      }
    

    }
    doSomething很可能會(huì)執(zhí)行一段時(shí)間,比如n秒,當(dāng)然了,在執(zhí)行這段代碼期間,self是無法被銷毀的,即使在外部,self已經(jīng)沒有任何引用了,self也要等到doSomething結(jié)束后才被銷毀。

那么,問題來了:既然self在執(zhí)行完doSomething后被銷毀了,那么后面的doOtherthing肯定也就無法執(zhí)行了,但是我們又必須讓它執(zhí)行起來。
這個(gè)時(shí)候,我們就要對(duì)__weak引用過的self再次進(jìn)行__strong引用一遍。
代碼如下:

__weak typeof(self) wself = self;
obj2.block: ^ (void) {
  __strong typeof(wself) sself = wself; 
  if (sself) { // 要判斷self是否存在,存在才能執(zhí)行它的方法
    [sself doSomething];
    // ... n秒后
    [sself doOtherthing];
  }
}

在block中,再執(zhí)行一遍__strong typeof(wself) sself = wself;后,self就不會(huì)立馬被銷毀了,就可以順利執(zhí)行完畢doSomethingdoOtherthing,然后在block執(zhí)行完畢后再銷毀self對(duì)象。

  • 總結(jié)
    聰明的同學(xué)看完了情況3,估計(jì)又有新的問題產(chǎn)生了:既然我要保證,在block中執(zhí)行完畢doOtherthing,我干嘛還要先在block外部用__weak引用一次self,然后在block內(nèi)部再次使用__strong對(duì)weakSelf引用一次?
    干嘛要浪費(fèi)兩步多余的引用,直接在block中使用self不就好了么?這樣即使,外部self沒有引用了,block內(nèi)部,self仍然被引用了???

本人水平有限,這種情況我也測(cè)試不出來,希望有測(cè)試過這種情況的同學(xué)可以分享一下結(jié)果給我!我將感激不盡?。?/p>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容