在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編譯器