RAC是一套基于Cocoa的FRP框架,它的优点是用户的输入转化为随时间改变的函数,取消了可变状态.在RAC的世界里,"万物"皆为信号,一个基础的信号创建,订阅,发送,销毁过程简单的可以用一下代码表示
// 创建信号时传递参数block:由 返回值RACDisposable 参数subscriber 代码块组成
@weakify(self);
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
@strongify(self);
// block代码块 会在信号订阅方法subscribeNext调用的时候执行
[subscriber sendNext:@"RAC"];
// 如果不再发送数据,最好发送信号完成,内部会自动调用[RACDisposable disposable]取消订阅信号。
[subscriber sendCompleted];
NSLog(@"subscriber == %@",subscriber);
RACDisposable *disposable = [RACDisposable disposableWithBlock:^{
// 销毁信号
// block调用时刻:当信号发送完成或者发送错误,就会自动执行这个block,取消订阅信号。
// 执行完Block后,当前信号就不在被订阅了。
NSLog(@"开始销毁");
}];
return disposable;
}];
// 订阅信号,才会激活信号.
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"x == %@",x);
}];
RAC的奇妙之处在于使用Block作为参数,Block可以封装了函数调用以及函数调用环境,然后在需要的地方调用.
当我们调用createSignal创建信号时,方法执行调用
RACDynamicSignal : 使用块实现其订阅行为的私有“RACSignal”子类
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
RACDynamicSignal *signal = [[self alloc] init];
signal->_didSubscribe = [didSubscribe copy];
return [signal setNameWithFormat:@"+createSignal:"];
}
此时产生信号,并用信号保存每个订阅者要调用的块.
创建信号后,调用订阅信号subscribeNext会执行
RACSubscriber
+ (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;
}
创建订阅者,并用属性保存订阅者Block,之后调用[self subscribe:o]
self是创建信号时的RACDynamicSignal所以调用[self subscribe:o]执行以下 这里类似类簇的应用
- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
NSCParameterAssert(subscriber != nil);
RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];
//subscriber用属性保存subscriber,用于在[subscriber sendNext:@"RAC"]执行时,调用[self.innerSubscriber sendNext:value]
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;
}
此时创建销毁者RACCompoundDisposable, RACPassthroughSubscriber当不被销毁时将所有事件传递给另一个订阅者的私有订阅者.如果每个订阅者要调用的块didSubscribe存在,创建RACScheduler(调度者用于控制何时何地执行工作)的子类RACSubscriptionScheduler(仅用于订阅的私有调度者),默认主线程执行block,调用self.didSubscribe(subscriber)
- (RACDisposable *)schedule:(void (^)(void))block {
NSCParameterAssert(block != NULL);
if (RACScheduler.currentScheduler == nil) return [self.backgroundScheduler schedule:block];
block();
return nil;
}
接着将返回didSubscribe初始化的地方createSignal:
当调用 [subscriber sendNext:@"RAC"];时会执行
subscriber 为前面RACPassthroughSubscriber 也是应用类簇
- (void)sendNext:(id)value {
if (self.disposable.disposed) return;
if (RACSIGNAL_NEXT_ENABLED()) {
RACSIGNAL_NEXT(cleanedSignalDescription(self.signal), cleanedDTraceString(self.innerSubscriber.description), cleanedDTraceString([value description]));
}
[self.innerSubscriber sendNext:value];
}
此时[self.innerSubscriber sendNext:value];便触发订阅者的block调用
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"x == %@",x);
}];
这样一个简单的信号创建,订阅,发送,销毁过程就结束了,整个过程应用类簇和block实现FRP
除了上述模式创建信号你也可以这样
RACReturnSignal
// 一个私有的“RACSignal”子类,它同步向任何订阅者发送信号,然后完成
[[RACSignal return:@"123456"] subscribeNext:^(id _Nullable x) {
NSLog(@"-----%@",x);
}];
RACErrorSignal
一个私有的“RACSignal”子类,它同步向任何订阅者
RACSignal *signal = [RACSignal error:[NSError errorWithDomain:@"" code:404 userInfo:nil]];
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
不同的信号用不同的子类创建,同时存储不同的属性
冷热信号
热信号 : 是主动的,即时没有订阅,它也会源源不断的推送,它可以有多个订阅者是一对多,集合与订阅者共享信息.
冷信号: 是被动的,每个订阅都是独立行为.每一订阅都会执行一次.
网友评论