03oc中block的循環引用 (一)

  1. @property (nonatomic, copy) void (^getCardInfo)(NSDictionary *cardInfo);
    @end
兩個點: copy和 block

我將block聲明為copy的原因是在代碼塊里面我可能會使用一些本地變量, 而block一開始是放在棧上的,只有copy后才會放到堆上。
如果加copy屬性,當其所在棧被釋放的時候,這些本地變量將變得不可訪問。一旦代碼執行到block這段就會導致bad access。

brush.getCardInfo = ^(NSDictionary *info){
         [self test];
}

但是這又帶來另一個問題,就是self的引用計數+1。這意味著很可能會導致循環引用。self持有brush,brush持有block,block持有self。結果就是內存泄漏。

解決辦法如下. 通過一種方式, 告訴 block 這個變量的引用計數不要+1
如果是 MRC的情況:

__block CurrentViewController *blockself = self;
brush.getCardInfo = ^(NSDictionary *info){
     [blockSelf test];
}

如果是 ARC的情況:

__weak CurrentViewController *blockself = self;
brush.getCardInfo = ^(NSDictionary *info){
     [blockSelf test];
}

1.解決辦法
簡而言之就是一句話的事情

__weak typeof (self) weakself = self;

經過上面的測試發現, 在加了__ weak 和__unsafe_unretained的變量引入后
TestCycleRetain方法可以正常秩序 dealloc 方法 , 而不轉換和用__block轉換的變量都會引起循環引用
因為防止循環引用的方法如下:

__unsafe_unretained TestCycleRetain *weakSelf = self;

網上大部分人的表述是"block 里面引用了 self 導致循環引用", 但是事實真的這樣的嗎? 我表示懷疑, 其實這種說話是不嚴謹的, 不一定是顯式地出現"self"字眼才會引起循環引用, 我們改一下代碼, 不通過屬性 self.arr 去訪問 arr 變量, 而是通過實例變量_ arr 去訪問, 如下
即使在你的代碼沒有顯式地出現"self", 也會出現循環引用, 只要你在 block 里用到了 self 所擁有的東西, 但對于這種情況, 目前我不知道如何排除掉循環引用 , 因為我們無法通過加__weak 聲明或者__block聲明去禁止 block 對 self 進行強引用或者強制增加引用計數, 對于 self.arr 的情況, 我們要分兩種環境去解決,

  1. MRC

    __block typeof(self) weakSelf = self,
    
  2. ARC

    __weak typeof(self) weakSelf = self, 其實__weak someClass *weakSelf = self也是 OK 的
    

解決方式與上述基本一致, 只不過將__ block 關鍵字換成了__ weak, 這樣的意思就是告訴 block, 咱們已經沒有任何的關系, 不要在內部對 self 進行 retain 了

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容