ReactiveCocoa(简称为RAC),是由Github开源的一个应用于iOS和OS开发的框架.
RAC 的核心思想:创建信号 - 订阅信号 - 发送信号 我们按照这个步骤来 一步一步的实现 并且探寻RAC 里面是怎么的一个原理
信号写法
- 第一种写法
NSArray *array = @[@"1", @"2", @"3", @"4", @"5"];
RACSignal *signal=[RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
NSLog(@"创建信号");
//发送信号
[subscriber sendNext:array];
return nil;
}];
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"订阅信号%@",x);
}];
- 第二种写法 上面的方式缩写
NSArray *array = @[@"1", @"2", @"3", @"4", @"5"];
[[RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
NSLog(@"创建信号");
//发送信号
[subscriber sendNext:array];
return nil;
}]subscribeNext:^(id _Nullable x) {
NSLog(@"订阅信号%@",x);
}];
- 为了便于理解 我们先按照顺序分步骤写 探寻每个方法里面的秘密
创建信号 内部的秘密
- 如我们下面这行代码,就是创建信号。RACSignal 的类方法createSignal,带block回调,里面有一个参数RACSubscriber。整个方法返回一个RACSignal对象。 创因为没有订阅者。称为冷信号
RACSignal *signal=[RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
NSLog(@"创建信号");
return nil;
}];
下面我们进入 createSignal方法看看里面怎么实现的
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
return [RACDynamicSignal createSignal:didSubscribe];
}
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
RACDynamicSignal *signal = [[self alloc] init];
signal->_didSubscribe = [didSubscribe copy];
return [signal setNameWithFormat:@"+createSignal:"];
}
看到createSignal方法里面 创建了一个 RACDynamicSignal对象,我们可以把它理解为一个动态信号。同时对一个didSubscribe这个block 进行了一个保存
订阅信号 内部的秘密
- 订阅信号 RACSignal 对象 调用一个方法 subscribeNext,方法 返回一个RACDisposable对象(可以先不看这个) ,写了subscribeNext 方法的信号,因为有了订阅者称为热信号。
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"订阅信号%@",x);
}];
下面我们进入 subscribeNext 方法看看 里面有什么
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
NSCParameterAssert(nextBlock != NULL);
RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
return [self subscribe:o];
}
//进入subscriberWithNext方法
+ (instancetype)subscriberWithNext:(void (^)(id x))next error:(void (^)(NSError *error))error completed:(void (^)(void))completed {
RACSubscriber *subscriber = [[self alloc] init];
subscriber->_next = [next copy];
subscriber->_error = [error copy];
subscriber->_completed = [completed copy];
return subscriber;
}
看到 subscribeNext里 调用subscriberWithNext里面 创建了一个 RACSubscriber 对象(这是一个有意思的现象 ,在上面 创建信号的里面 我们见到了 创建方法里 保存了一个didSubscribe block 也是RACSubscriber,它的实质就是创建信号的block)。同时 对 _next _error _completed 三个block 进行了保存 并执行了RACSubscriber
发送信号 内部的秘密
- 就一句简单 sendNext: 如果没有这句,我是订阅者是没法获取数据的
// 发送信号
[subscriber sendNext:@“我是内容”];
下面我们进入 sendNext 方法看看 里面有什么
sendNext 在 多个类都有此方法

点击 RACSubject sendNext:
里面是酱紫的
- (void)sendNext:(id)value {
[self enumerateSubscribersUsingBlock:^(id<RACSubscriber> subscriber) {
[subscriber sendNext:value];
}];
}
调用 [RACSubject sendNext] 时
RACSubject就会遍历一遍自己的subcribers数组,并调用各数组元素(subscriber)准备好的Block
继续点击RACSubscriber sendNext
- (void)sendNext:(id)value {
@synchronized (self) {
void (^nextBlock)(id) = [self.next copy];
if (nextBlock == nil) return;
nextBlock(value);
}
}
又见到了 熟悉的面孔 上面 订阅信号保存的一个_next block ,
把 之前在订阅信号保存的_next block 进行赋值并执行。
整理一下
看了一会 这么多方法,这些貌似有联系,但是又模模糊糊的。我们和代码结合起来看
NSArray *array = @[@"1", @"2", @"3", @"4", @"5"];
一. //创建信号
1.创建了一个 RACDynamicSignal
2.保存了一个 didSubscribe block
RACSignal *signal=[RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
NSLog(@"创建信号");
三.//发送信号
1.执行订阅信号保存的_next block 。
[subscriber sendNext:array];
return nil;
}];
二.//订阅信号
1.保存了_next _error _completed 三个block
2.执行创建信号时所保存的didSubscribe block
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"订阅信号%@",x);
}];
看了大约能明白 都是block 在互相关联
我们在用图了解一些整个信号的运行原理

创建信号 - 订阅信号 - 发送信号 就是这样实现的
不得不佩服ReactiveCocoa 的作者们,给我们在开启了一座新的大门。它的编程思想真的值得我们去学习一下。
结尾:水平有限,代码也很烂,一直在努力学习中,大家多多包涵。
网友评论