一、RAC是什么?
RAC--ReactiveCocoa(RAC) 是GitHub一个开源框架!
RAC--函数响应式编程框架!
二、RAC有什么用?
帮助我们更简单的处理事件
三、引入RAC OC版本
pod 'ReactiveObjC','3.0.0'
四、详解
1、RACSignal:信号类
- 创建RACSignal创建一个信号!!(默认是冷信号)
- 通过订阅者订阅这个信号!(变成热信号)
- 发送信号!
分部代码
第一步:利用RACSignal创建一个冷信号
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe;
在这个类方法中, 有一个参数didSubscribe, 这是一个block, 这个block是一个参数为id类型, 遵守RACSubscriber协议的对象, 返回值为RACDisposable ****类型的block***.
//1、创建信号 目前是冷信号
//didSubscribe调用:只要一个信号被订阅就会被调用
//didSubscribe作用: 利用subscriber发送数据
RACSignal * signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"signal has been created");
//***必须得有返回值***
return nil;
}];
代码写到这里, 这个block中的代码会执行吗? 显然不会, 那么, 这段代码什么时候执行呢?
第二步:这时候就需要订阅信号,由冷信号->热信号
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock;
这段代码中, 又有一个block参数, 这个block是一个参数为id类型的对象, 返回值为空的block, 信号订阅时, 我在这个block中什么也不做, 上面的打印同样能够执行:
//2、订阅信号 将第一步的冷信号 变为 热信号
//nextBlock调用:只要订阅者发送信息就会调用
//nextBlock作用:处理数据,展示UI界面
[signal subscribeNext:^(id x) {
//x : 信号发送的内容
NSLog(@"AAA = %@",x);
}];
第三步:发送信号
- (void)sendNext:(id)value;
//1、创建信号
//didSubscribe调用:只要一个信号被订阅就会被调用
//didSubscribe作用: 利用subscriber发送数据
RACSignal * signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
//3、发送信号 subscriber
[subscriber sendNext:@"发送信号"];
//有返回值
return nil;
}];
底层实现
我们来看一下这个内部是怎么实现的
第一步:创建信号
RACSignal_createSignal.png
RACDynamicSignal_createSignal.png
其中signal->_didSubscribe = [didSubscribe copy];
这句代码将didSubscribe
这个block
保存在对象的属性中.
第二步:订阅信号
RACSignal_subscribeNext.png上面这个函数就是创建了一个RACSubscriber
对象,然后被调用进入真正的订阅函数。
根据创建信号的底层方法,可以看到信号对象是RACDynamicSignal
最终的订阅函数
RACDynamicSignal_subScribe.png
从上图我们可以看到, didSubscribe
这个block
在信号订阅的时候被调用, 在调用的同时, 把subscriber
这个参数传给block
, 所以我们在
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
NSLog(@"signal has been created");
[subscriber sendNext:@"subscriber send"];
return nil;
}];
这个代码块内部是可以拿到subscriber这个对象的, 然后我再调用sendNext这个方法, 会出现什么情况呢?
第三步:发送信号
RACSubscriber_sendNext.png根据创建订阅信号的函数,可以找到
创建订阅者.png 进一步观察.png
可以看到这一个函数中,将block
进行了属性的保存。
2、RACDisposable :取消订阅类
看到createSignal
的block
是有返回值的RACDisposable
RACSignal * signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
RACDisposable * disposible = [RACDisposable disposableWithBlock:^{
NSLog(@"disposible");
}];
//有返回值
return disposible;
}];
运行如下图
运行.png
可以看到的是: 这个返回值是RACDisposable
类型的, 然后我们创建一个RACDisposable
对象是用+ (instancetype)disposableWithBlock:(void (^)(void))block
这个类方法, 同样参数也是一个block
, 但是这个block
很快就被调用了, 这是为什么呢?
在subscribeNext:
方法调用时, 赋值给了subscriber
的disposable
属性(可以先这么理解), 当subscriber
生存周期结束时, 就会调
- (void)dealloc {
[self.disposable dispose];
}
所以这个时候
RACDisposable *disposable = [RACDisposable disposableWithBlock:^{
NSLog(@"disposable");
}];
return disposable;
这段代码中的打印就会执行了.
但当subscriber
被强引用时, dealloc
方法不被调用, disposable
也不会被调用.
如果subscriber被强引用时, 我又想取消订阅, 应该怎么做呢?
subscribeNext:这个方法是有返回值的, 这个返回值其实就是上面
didSubscribeblock的返回值(可以先这么理解)
我用一个变量接收一样, 然后手动disposable即可:
那么RACDisposable是做什么用的呢?
这个类可以帮助我们取消订阅, 当信号发送完毕了或者失败了之后取消订阅, 并调用指定的代码.
3、RACSubject类
在RAC中, 还有一个类非常重要, 也很特殊, 叫做RACSubject
, 这个类即可以创建信号, 也可以发送信号. 代码如下:
RACSubject *subject = [RACSubject subject];
[subject subscribeNext:^(id _Nullable x) {
NSLog(@"subject has been subscribed %@", x);
}];
[subject sendNext:@"subject has been sended"];
subject发送信号
所以, 用RACSubject
的好处就是: 可以订阅多个信号, 最后发送信号的时候一起调用.
RACSubject
的本质其实和RACSignal是一样的, 那为什么它又可以创建信号, 又可以订阅信号呢?
在OC中, 是没有多继承的概念的, 要想实现多继承的效果, 可以先继承一个类, 然后再实现一个或者多个协议, 这样就实现了多继承的效果
继承RACSignal.png五、RAC实战
那么, 说了这么多, 这个RAC有什么用呢?
用处大了, 因为它可以实现KVO , 代理, 通知, block的功能, 集多种功能于一身, 当你用了RAC之后, 你可以利用RAC实现以上设计模式能实现的功能.
参考网址:http://www.jianshu.com/p/381b29b01457 (学豆)
网友评论