RAC是一个函数响应编程框架。
先来一个简单的RAC使用:
RACSignal使用步骤:
1.创建信号 + (RACSignal *)createSignal:(RACDisposable * (^)(id subscriber))didSubscribe
2.订阅信号,才会激活信号. - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock
3.发送信号 - (void)sendNext:(id)value
- (void)test_signal
{
// 1.创建信号
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
// 3.发送信号
NSLog(@"%@:发送信号", NSStringFromSelector(_cmd));
[subscriber sendNext:@(1)];
return nil;
}];
// 2.订阅信号
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"%@:x:%@", NSStringFromSelector(_cmd), x);
}];
}
一个信号的简单使用,就是如上代码所示。
我们也可以把它按照下面的去理解:
- (void)test_signal_detail
{
// 当订阅信号的时候,需要处理的事情,这里面会发送信号
RACDisposable *(^doSomethingWhenSubscribeSignal)(id<RACSubscriber>) = ^RACDisposable *(id<RACSubscriber> subscriber) {
// 3.发送信号
NSLog(@"%@:发送信号", NSStringFromSelector(_cmd));
[subscriber sendNext:@(1)];
return nil;
};
// 1.创建信号
RACSignal *signal = [RACSignal createSignal:doSomethingWhenSubscribeSignal];
// 当收到信号的时候,需要处理的事情
void (^doSomethingWhenReceiveSignal)(id) = ^void (id x) {
NSLog(@"%@:x:%@", NSStringFromSelector(_cmd), x);
};
// 2.订阅信号
[signal subscribeNext:doSomethingWhenReceiveSignal];
}
注意上述代码中的注释,可以按照如下的描述:
1.创建信号的时候,需要保存一个blockA(此block的作用是:当订阅信号的时候,需要做的事情)
2.订阅信号的时候,需要保存一个blockB(此block的作用是:当收到信号发送值的时候,需要做的事情)
如果在设计代码的时候我们就会这样考虑设计:
1.信号会一直持有blockA,理论上订阅一个信号的时候,订阅所做的事情都是一样的
2.信号不会持有blockB,一个订阅信号,然后收到信号发送值的时候,处理的事情是不同的。
如下的3个关键函数的实现:
1.创建信号:[RACSignal createSignal...]
RACSignal.m
创建一个RACDynamicSignal的实例,就是把blockA当做参数传递给RACDynamicSignal
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
return [RACDynamicSignal createSignal:didSubscribe];
}
RACDynamicSignal.m
直接简单的保存blockA
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
RACDynamicSignal *signal = [[self alloc] init];
signal->_didSubscribe = [didSubscribe copy];
return [signal setNameWithFormat:@"+createSignal:"];
}
2.订阅信号:[signal subscribeNext...]
RACSignal.m
用函数B创建一个订阅者RACSubscriber,信号订阅订阅者([self subscribe:o]字面理解),或者说用这个订阅者处理此信号,信号没有持有blockB
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
NSCParameterAssert(nextBlock != NULL);
RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
return [self subscribe:o];
}
RACSubscriber.m
RACSubscriber持有了blockB
+ (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;
}
RACDynamicSignal.m
订阅者处理信号,里面有一堆复杂的,但是关键的就是:self.didSubscribe(subscriber),表明调用了blockA
- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
NSCParameterAssert(subscriber != nil);
RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];
subscriber = [[RACPassthroughSubscriber alloc] initWithSubscriber:subscriber signal:self disposable:disposable];
if (self.didSubscribe != NULL) {
RACDisposable *schedulingDisposable = [RACScheduler.subscriptionScheduler schedule:^{
RACDisposable *innerDisposable = self.didSubscribe(subscriber);
[disposable addDisposable:innerDisposable];
}];
[disposable addDisposable:schedulingDisposable];
}
return disposable;
}
3.发送信号:[subscriber sendNext...]
RACSubscriber.m
发送信号的时候,就是直接使用blockB
- (void)sendNext:(id)value {
@synchronized (self) {
void (^nextBlock)(id) = [self.next copy];
if (nextBlock == nil) return;
nextBlock(value);
}
}
在整个RAC实现的过程中订阅者都是被隐藏的,都是通过一个协议去实现的:

具体看里面的定义就知道了。
网友评论