本文是对ReactiveObjC原理简介
一、流程分析
ReactiveObjC
主要有三个关键类:
1、RACSignal
信号
RACSignal
是各种信号的基类,其中RACDynamicSignal
是用的最多的动态信号
2、RACSubscriber
订阅者
RACSubscriber
是实现了RACSubscriber
协议的订阅者类,这个协议定义了4个必须实现的方法
@protocol RACSubscriber <NSObject>
@required
- (void)sendNext:(nullable id)value; //常见
- (void)sendError:(nullable NSError *)error; //常见
- (void)sendCompleted; //常见
- (void)didSubscribeWithDisposable:(RACCompoundDisposable *)disposable;
@end
RACSubscriber
主要保存了三个block,跟三个常见的协议方法一一对应
@property (nonatomic, copy) void (^next)(id value);
@property (nonatomic, copy) void (^error)(NSError *error);
@property (nonatomic, copy) void (^completed)(void);
3、RACDisposable
清洁工
RACDisposable
主要是对资源的释放处理,其中使用RACDynamicSignal
时,会创建一个RACCompoundDisposable
管理清洁工对象。其内部定义了两个数组,一个是_inlineDisposables[2]
固定长度2的A fast array
,超出2个对象的长度由_disposables
数组管理,_inlineDisposables
数组速度快,两个数组都是线程安全的。
4、简单信号调用流程
结合以下代码分析
//1、创建信号
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
//任何时候,都可以发送信号,可以异步
[subscriber sendNext:@"发送信号"];
[subscriber sendCompleted];
return nil;
}];
//2、订阅信号
[signal subscribeNext:^(id _Nullable x) {
//收到信号时
NSLog(@"信号内容:%@", x);
}];
调用流程如下:
流程.png
注意:如果didSubscribe
是异步执行,则会先返回RACDisposable
,然后执行sendNext:
二、主要类分析
关于ReactiveObjC
所有class
的继承关系
图片来自(http://www.cnblogs.com/CoderEYLee/p/Object-C-0010.html)[http://www.cnblogs.com/CoderEYLee/p/Object-C-0010.html]
1、RACStream
RACStream
是所有信号类的父类,也是一个抽象类。它定义了五个子类必须实现的方法:
+ (__kindof RACStream<ValueType> *)empty;
+ (__kindof RACStream<ValueType> *)return:(nullable ValueType)value;
- (__kindof RACStream *)bind:(RACStreamBindBlock (^)(void))block;
- (__kindof RACStream *)concat:(RACStream *)stream;
- (__kindof RACStream *)zipWith:(RACStream *)stream;
RACStream
还定义了一个Operations
的分类,分类中定义并实现了各种信号处理方法,都是使用以上5个方法,直接或间接实现的。子类继承了RACStream
之后,便可使用Operations
分类中的所有方法。
2、RACSignal
RACSignal
是个核心的信号类,继承并实现了父类RACStream
中的5个必要方法。
①empty
实现
//返回一个空信号
return [[[self alloc] init] setNameWithFormat:@"+empty"];
②return
实现
//将传入对象保存,并返回信号
RACReturnSignal *signal = [[self alloc] init];
signal->_value = value;
③bind
实现
//bind调用了一个传入值,并且返回信号的block
typedef RACSignal * _Nullable (^RACSignalBindBlock)(ValueType _Nullable value, BOOL *stop);
//bind内部调用RACSignalBindBlock之后,得到新的信号,然后给新的信号发送sendNext:,并在sendNext:内部给原订阅者发送sendNext:信号,传入包装后的值
//简化后的bind
- (RACSignal *)bind:(RACSignalBindBlock (^)(void))block {
return [[RACSignal createSignal:^(id<RACSubscriber> subscriber) {
//拿到实现的block
RACSignalBindBlock bindingBlock = block();
return [self subscribeNext:^(id x) {
BOOL stop = NO;
//调用数据处理的block
[bindingBlock(x, &stop) subscribeNext:^(id x) {
//并且把数据传递给原订阅者
[subscriber sendNext:x];
}];
}];
}] setNameWithFormat:@"[%@] -bind:", self.name];
}
//调用
[[self.textField.rac_textSignal bind:^RACSignalBindBlock _Nonnull{ return ^RACSignal*(id value, BOOL *stop){
//bind实现的block内部,拿到数据,包装成信号返回出去
return [RACSignal return:[NSString stringWithFormat:@"hello: %@",value]];
};
}] subscribeNext:^(id _Nullable x) {
NSLog(@"bind : %@",x); // hello: "x"
}];
④concat
实现
//concat简化后
- (RACSignal *)concat:(RACSignal *)signal {
return [[RACSignal createSignal:^(id<RACSubscriber> subscriber) {
//先给信号本身发送sendNext:
return [self subscribeNext:^(id x) {
[subscriber sendNext:x];
} error:^(NSError *error) {
[subscriber sendError:error];
} completed:^{
//执行完成之后,再给signal发送订阅的消息
[signal subscribe:subscriber];
}];
}] setNameWithFormat:@"[%@] -concat: %@", self.name, signal];
}
//调用
RACSignal *signalA = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
[subscriber sendNext:@"signalA"];
[subscriber sendCompleted];
return nil;
}];
RACSignal *signalB = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
[subscriber sendNext:@"signalB"];
[subscriber sendCompleted];
return nil;
}];
// 把signalA拼接到signalB后,signalA发送完成,signalB才会被激活 顺序执行
[[signalA concat:signalB] subscribeNext:^(id _Nullable x) {
//先拿到 signalA 的结果 , 再拿到 signalB 的结果 , 执行两次
NSLog(@"concat result = %@", x);
}];
⑤zipWith
实现
//简化后的zipWith
- (RACSignal *)zipWith:(RACSignal *)signal {
return [[RACSignal createSignal:^(id<RACSubscriber> subscriber) {
NSMutableArray *selfValues = [NSMutableArray array];
NSMutableArray *otherValues = [NSMutableArray array];
__block NSInteger completedCount = 0;
void (^sendNext)(void) = ^{
@synchronized (selfValues) {
//当两个信号都执行完成时,将返回结果打包成元祖返回给原信号
//每次都是取数组的第1个元素,取完之后,数组清空,所以信号的数据都是一一对应的
RACTuple *tuple = RACTuplePack(selfValues[0], otherValues[0]);
[selfValues removeObjectAtIndex:0];
[otherValues removeObjectAtIndex:0];
[subscriber sendNext:tuple];
if (completedCount == 2) {
//当前信号完成
[subscriber sendCompleted];
}
}
};
//订阅执行第一个信号
[self subscribeNext:^(id x) {
[selfValues addObject:x ?: RACTupleNil.tupleNil];
completedCount++;
sendNext();
}];
//订阅执行第二个信号
[signal subscribeNext:^(id x) {
[otherValues addObject:x ?: RACTupleNil.tupleNil];
completedCount++;
sendNext();
}];
return [RACDisposable disposableWithBlock:^{}];
}] setNameWithFormat:@"[%@] -zipWith: %@", self.name, signal];
}
//调用
RACSignal *zipSignal = [zipSignalA zipWith:zipSignalB];
[zipSignal subscribeNext:^(id _Nullable x) {
// x 是一个元祖
RACTupleUnpack(NSNumber *a, NSNumber *b) = x;
}];
这里有一篇对ReactiveObjC 详细的原理说明:
ReactiveObjC详细原理
网友评论