跳出 Block 的坑
使用過 Block 的開發(fā)者都有一個意識就是猬腰,要防止 retain cycel(循環(huán)引用)募谎。如何防止 retain cycle 也有很多文章描述過了士修,但是你的做法真的是安全的嗎智什?下面我們來探究一下 weak-strong dance.
下面來看一下代碼:
- (void)blockRetainCycleProblem {
self.block = ^{
NSLog(@"%@", @[self]);
};
}
上面一段代碼很明顯就是出現(xiàn)了 retain cycel持灰,于是你的解決辦法就是如下了:
- (void)blockRetainCycleProblemAnswer0 {
__weak typeof(self) weakSelf;
self.block = ^{
NSLog(@"%@", @[weakSelf]);
};
}
上面的解決方案真的安全嗎榨乎?
如果在 block 執(zhí)行之前怎燥,self 被主線程釋放掉了,而 weakself 卻是對 self 的弱引用蜜暑,所以根據(jù) ARC 的規(guī)則铐姚,weakself 會被賦值為 nil(不明白為何為 nil ,可以點(diǎn)擊這里)史煎。當(dāng) weakself 為 nil,block 中執(zhí)行的代碼就會導(dǎo)致程序 crash谦屑。
于是,又出現(xiàn)下面這種解決方式:
- (void)blockRetainCycleProblemAnswer1 {
__weak typeof(self) weakSelf;
self.block = ^{
__strong typeof(weakSelf) strongSelf = weakSelf;
NSLog(@"%@", @[strongSelf]);
};
}
為什么上面這種做法可以防止程序 crash 呢篇梭?
因?yàn)?strongSelf 強(qiáng)引用了一次 self ,這時候 self 的 retainCount 為2氢橙,即是 self 超出了作用域,引用它的還有 strongSelf 對象恬偷,其 retainCount 依然是1悍手,對象還未被釋放,依然存在。
更安全的解決方式如下:
- (void)blockRetainCycleProblemAnswer2 {
__weak typeof(self) weakSelf;
self.block = ^{
__strong typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
NSLog(@"%@", @[strongSelf]);
}
};
}
防止 strongSelf 被釋放坦康,而執(zhí)行相關(guān)操作竣付,導(dǎo)致程序 crash.