我们知道,在使用 block 的时候,为了避免产生循环引用,通常需要使用 weakSelf 与 strongSelf,写下面这样的代码:
__weak typeof(self) weakSelf = self;
[self doSomeBackgroundJob:^{
__strong typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
...
}
}];
那么请问:为什么 block 里面还需要写一个 strong self,如果不写会怎么样?
在 block 中先写一个 strong self,其实是为了避免在 block 的执行过程中,突然出现 self 被释放的尴尬情况。通常情况下,如果不这么做的话,还是很容易出现一些奇怪的逻辑,甚至闪退。
我们以AFNetworking中的AFNetworkReachabilityManager.m的一段代码举例:
__weak __typeof(self)weakSelf = self;
AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {
__strong __typeof(weakSelf)strongSelf = weakSelf;
strongSelf.networkReachabilityStatus = status;
if (strongSelf.networkReachabilityStatusBlock) {strongSelf.networkReachabilityStatusBlock(status);
}
};
如果没有strongSelf的那行代码,那么后面的每一行代码执行时,self都可能被释放掉了,这样很可能造成逻辑异常。
特别是当我们正在执行 strongSelf.networkReachabilityStatusBlock(status); 这个 block闭包时,如果这个 block 执行到一半时 self 释放,那么多半情况下会 Crash。
这里有一篇文章详细解释了这个问题:
昨天的读者中,拓荒者 和 陈祥龙 同学在评论中也正确回答出了本题。
拓荒者:
1.在block里使用strongSelf是防止在block执行过程中self被释放。 2.可以通过在执行完block代码后手动把block置为nil来打破引用循环,AFNetworking就是这样处理的,避免使用者不了解引用循环造成内存泄露。实际业务中暂时没遇到这种需求,请巧哥指点什么情况下会有这种需求。
陈祥龙:
strongSelf 一般是在为了避免 block 回调时 weak Self变成了nil ,异步执行一些操作时可能会出现这种情况,不知道我说得对不对。因业务需要不能使用weakSelf 这种情况还真没遇到过
另外,还有读者提了两个有意思的问题,大家可以思考一下:
Yuen 提问:“数组” 和 “字典” 的 enumeratXXXUsingBlock: 是否要使用 weakSelf 和 strongSelf 呢?
潇湘雨同学提问:block 里 strong self 后,block 不是也会持有 self 吗?而 self 又持有 block ,那不是又循环引用了?