RAC(ReactiveCocoa)介绍(五)——RACPassthroughSubscriber
上一篇整体分析了RAC的信号流程,这样对RAC的工作原理有了整体的认识。 接下来将逐步深入了解RAC实现的底层。
RACPassthroughSubscriber类
在上一篇文章的流程分析中,真正的订阅者是RACPassthroughSubscriber类,它将创建信号、订阅者与销毁者进行了关联。 在RACPassthroughSubscriber类的头文件中,声明了一个RACSignal类的成员变量。
@property (nonatomic, unsafe_unretained, readonly) RACSignal *signal;
在声明的属性中,定义了signal为unsafe_unretained,意味着signal为弱引用,但又与weak属性不同。weak属性当为nil时,对象会自动执行释放功能,导致该对象无法继续被使用。而unsafe_unretained同样作为弱引用,当为nil时却指针不会自动释放,保留一个野指针。如果使用此指针,程序会抛出 BAD_ACCESS 的异常。
在此处多问一个为什么,此处信号为什么要使用unsafe_unretained而不是weak属性修饰? 找了网上的几处分析,都在说下面这句: 这里之所以不是weak,是因为引用RACSignal仅仅只是一个DTrace probes动态跟踪技术的探针。如果设置成weak,会造成没必要的性能损失。
个人理解:unsafe_unretained属性不会自动将signal变为nil,而weak属性会自动置为nil。当signal置为nil时,当前signal不再是一个信号类型的对象,就无法再继续执行订阅信号、发送信号动作。所以要使用unsafe_unretained属性保留当前signal的类型,即使变成了野指针。
_signal成员变量传值
首先,此处的成员变量signal声明为RACSignal类,是RACPassthroughSubscriber类实例化方法执行时传入的。而该信号又是从RACDynamicSignal传来的,RACDynamicSignal持有了当前的subscribe;subscribe继续向上溯源,找到了在RACSignal类中的[self subscribe:o]方法。那么答案已经显而易见了,unsafe_unretained属性的声明,就是为了防止在此过程中的循环引用。
RACSignal弱引用导图
在RACSignal类的订阅方法subscribeNext方法中,当执行订阅信号时,self通过LLDB打印出的却是RACDynamicSignal类。
self打印信息
首先RACDynamicSignal类是RACSignal类的子类,此处进行了RACSignal类的分类扩展在分类中实现了subscribeNext方法。在创建信号时,信号类为RACDynamicSignal类。
RACSignal分类
在发送信号时,打印subscriber会发现其所属类为RACPassthroughSubscriber。
打印结果
self.innerSubscriber对象为RACSubscriber类创建的,最终是执行RACSubscriber类下的sendNext方法,执行nextBlock。在执行时,@synchronized (self)用于保证线程安全
RACPassthroughSubscriber发送信号实现
以上就是针对RACPassthroughSubscriber类的实现进行了一个简单的分析,后续会不断补充、修改。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- MyBatis结果集映射
- Hadoop分布式集群环境搭建
- 使用Hadoop统计日志数据
- Mybatis在接口上使用注解配置SQL语句以及接口与xml一起使用
- 分布式计算框架MapReduce
- 安装webpack后,执行webpack -v命令时报错:SyntaxError: Block-sc
- SpringMVC数据类型转换器与国际化配置
- 分布式资源调度——YARN框架
- 在SpringMVC中使用数据验证组件——hibernate-validator
- 我的 2020 iOS BAT 面试心得
- Java操作HDFS开发环境搭建以及HDFS的读写流程
- HDFS伪分布式环境搭建
- 初识Hadoop
- SpringMVC返回JSON数据以及文件上传、过滤静态资源
- SpringMVC返回数据到视图