Block的循環引用

在ios常見的循環引用中曾經提到過block:ios

看看上面最基本的block循環應用,self包含block,block包含了self中的變量val,因此造成了循環應用,編譯器給出了循環引用的警告,固然不是全部的block循環引用編譯器都能給出警告,因此不要只依賴編譯器的警告來判斷循環引用,如:session

解決的辦法固然是使用__weak來修飾selfasync

__weak typeof(self) weakSelf = self;
blkk =  ^{
    [weakSelf showLog];
};
blkk();

-------------------------------凌亂分割線-------------------------------spa

正常在棧上的block引用self是不會引發循環應用的,因此能夠不使用weak來修飾selfcode

void (^blkk)(void) =  ^{
    [self showLog];
};
blkk();

可是由於block的使用附有__strong的緣由,雖然不會有循環引用,可是也會起到延長self對象的生命週期的效果,直到棧上的block釋放了,纔會釋放self。對象

所以釋放self可能會讓程序出現問題,假如self監聽了某些通知而修改公共資源什麼的,因此這種狀況下最好也使用weakself。生命週期

固然你也可能不但願self提早釋放,由於你的block回調後須要進行完整操做,假如self釋放了,你沒法在block回調後來處理一些其餘的事情,這時候你能夠選擇不使用weakself,也可使用weakself+strongself。先看看weakself+strongself的寫法:ci

__weak __typeof__(self) weakSelf = self;

createdTask = [self.sessionManager
              dataTaskWithRequest:request
              completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
              dispatch_async(self.responseQueue, ^{
                  __strong __typeof__(weakSelf) strongSelf = weakSelf;
.....

上面是AFNetworking的源碼,在block前用了weakself,在block裏用了strongself,這樣作和直接不使用weakself有什麼區別呢。資源

  block回調前結束self block回調後結束self
不使用weakself self 不釋放 self不釋放
weakself+strongself self已釋放 self不釋放
使用weakself self已釋放 self已釋放

因此根據狀況的不一樣,你們能夠選擇使用哪一種方式。固然最無腦的推薦仍是使用weakself編譯器

相關文章
相關標籤/搜索