为什么 weakSelf 需要配合 strong self 使用
2016-12-15 16:47
357 查看
我们知道,在使用 block 的时候,为了避免产生循环引用,通常需要使用 weakSelf 与 strongSelf,写下面这样的代码:
__weak typeof(self) weakSelf = self;[self doSomeBackgroundJob:^{ __strong typeof(weakSelf)
strongSelf = weakSelf; if (strongSelf) { ... }}];
在 block 中先写一个 strong self,其实是为了避免在 block 的执行过程中,突然出现 self 被释放的尴尬情况。通常情况下,如果不这么做的话,还是很容易出现一些奇怪的逻辑,甚至闪退。
我们以 AFNetworking 中
如果没有 strongSelf 的那行代码,那么后面的每一行代码执行时,self 都可能被释放掉了,这样很可能造成逻辑异常。
特别是当我们正在执行
这里有一篇文章详细解释了这个问题:https://dhoerl.wordpress.com/2013/04/23/i-finally-figured-out-weakself-and-strongself/
昨天的读者中,拓荒者 和 陈祥龙 同学在评论中也正确回答出了本题。
另外,还有读者提了两个有意思的问题,大家可以思考一下:
Yuen 提问:“数组” 和 “字典” 的
潇湘雨同学提问:block 里 strong self 后,block 不是也会持有 self 吗?而 self 又持有 block ,那不是又循环引用了?
__weak typeof(self) weakSelf = self;[self doSomeBackgroundJob:^{ __strong typeof(weakSelf)
strongSelf = weakSelf; if (strongSelf) { ... }}];
在 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。
这里有一篇文章详细解释了这个问题:https://dhoerl.wordpress.com/2013/04/23/i-finally-figured-out-weakself-and-strongself/
昨天的读者中,拓荒者 和 陈祥龙 同学在评论中也正确回答出了本题。
另外,还有读者提了两个有意思的问题,大家可以思考一下:
Yuen 提问:“数组” 和 “字典” 的
enumeratXXXUsingBlock:是否要使用 weakSelf 和 strongSelf 呢?
潇湘雨同学提问:block 里 strong self 后,block 不是也会持有 self 吗?而 self 又持有 block ,那不是又循环引用了?
相关文章推荐
- Android屏幕适配经验谈
- Class.forName的作用及用newInstance()和new创建对象的区别
- HTTP请求跨域问题,解决模棱两可。
- Logistic 回归
- 真机上运行monkeyrunner python脚本踩坑系列一
- 在Ubuntu16.04下编译OPENJDK8
- Hibernate 参数设置一览表
- Java按图片像素大小进行筛选
- stack smashing detected,程序段错误
- vue概念及基础学习
- 内存测试分享文档
- 面向对象的设计模式
- dev LayoutControl布局控件
- 边框、内阴影、背景图片、背景颜色、外阴影的呈现级别
- Mysql学习(四)
- block 什么时候需要构造循环引用
- LeetCode #226 - Invert Binary Tree - Easy
- spring annotation 注入static 属性
- JAVA远程连接linux服务器读取文件(JSch)
- MySql中利用insert into select 准备数据uuid主键冲突