RAC的API

2019-06-17  本文已影响0人  深海时代

信号类:有数据产生的时候

RACSignal;

实质  RACDynamicSignal  -> didSubscribe(block)

RACSubject               -> subscribers(数组)

RACReplaySubject    -> valuesReceived(数组)

不同的信号订阅方式不同

RACDynamicSignal: 1.创建订阅者 RACSubscriber  2.执行didSubscribe

RACSubject:1.创建订阅者 RACSubscriber  2.保存订阅者

RACReplaySubject: 1.创建订阅者 RACSubscriber  2.拿到当前创建的订阅者,发送之前保存的所有值

订阅者:发送数据 执行nextBlock

RACSubscriber

RACSubject

RACReplaySubject

信号触发结构

A  初始化信号内容;B  信号订阅;C  信号发送回调;D  信号发送

A createSignal后挂block(不触发任何操作)

B subscribeNext(触发A)

C subscribeNext后挂block(不触发任何操作)

D sendNext(触发C)

B->A,D->C,我们常将D写在A里构成 B->A->D->C;

炒饭模式

具体实现

1.createSignal

创建 RACDynamicSignal*  传入 didSubscribe(block)

2.subscribeNext

初始化一个RACSubscriber*,并把 订阅回调block赋给RACSubscriber* ->next

实现  RACDynamicSignal*  subscribe: 包含订阅回调block的订阅者(RACSubscriber*)

初始化一个RACPassthroughSubscriber*,->innerSubscriber *传入RACSubscriber*,->signal*传入RACDynamicSignal*,当信号的didSubscribe不为空时  进行某些判断后 执行didSubscribe并将RACPassthroughSubscriber* 当做参数传入

3.sendNext:value

取RACPassthroughSubscriber*->innerSubscriber 执行 sendNext

RACSubscriber*执行next(value)方法,next为订阅回调block

平台模式

具体实现

1.createSignal

创建 RACDynamicSignal*  传入 didSubscribe(block)

2.[RACDynamicSignal* publish];

创建一个RACMulticastConnection对象,把RACDynamicSignal*传给 ->sourceSignal,初始化一个RACSubject*传给 ->signal;

3.[connection.signal subscribeNext:^(id  _Nullablex) { }];

初始化一个RACSubscriber*,并把 订阅回调block赋给->next

实现  RACSubject*  subscribe: 包含订阅回调block的订阅者(RACSubscriber*)

初始化一个RACPassthroughSubscriber*,->innerSubscriber *传入RACSubscriber*,->signal*传入RACSubject*。

将RACPassthroughSubscriber*添加到RACSubject*->subscribers里。

4.[connection connect];

RACMulticastConnection*的sourceSignal属性执行  [RACDynamicSignal* subscribe:RACSubject*]

初始化一个RACPassthroughSubscriber*,->innerSubscriber *传入传入RACSubject*,->signal*传入RACSubject*,当信号的didSubscribe不为空时  进行某些判断后 执行didSubscribe并将RACPassthroughSubscriber* 当做参数传入

5.sendNext:value

遍历RACSubject*->subscribers 取subscriber 分别执行 sendNext

RACSubscriber*执行next(value)方法,next为订阅回调block

不同订阅者,发送信号的方式不同

[RACSubscriber  sendNext] :  执行nextBlock

[RACSubject  sendNext] :  遍历自身subscribers,让他们执行nextBlock

[RACReplaySubject sendNext] :  1.保存发送的值 2.遍历父类RACSubject的subscribers,让他们执行nextBlock

rac常用的宏

1.RAC(self.name_lb,text)=self.name_tf.rac_textSignal;

将前一个属性绑定为后一个属性,当后一个属性发生变化时自动同步给前一个属性。

2.[RACObserve(self,self.name)subscribeNext:^(id  _Nullablex) {}];

监听一个属性,每当这个属性发生变化时执行block;

3.@weakify(_name);@strongify(_name); 

弱引用/强引用

4.RACTuple*tuple=RACTuplePack(@10,@"name");

将一个数据集合包装成元组;

5.selfrac_liftSelector:@selector(updateUI:data:)withSignals:hotSignal,newSignal,nil];

类线程组操作,当所有信号发送完毕后执行@selector,形参依此为信号数据。

raccommand

RACCOMMAND

执行顺序:

[commandexecute:@123];

SignalBlock();

command.executionSignals.next();

signalBlock返回的信号的didSubscribe();

内部connection.signal.next();

bind:

- (RACSignal *)bind:(RACSignalBindBlock (^)(void))block;

此方法的参数是一个以 RACSignalBindBlock()为返回的block;

此方法返回一个信号racSingal_A;

此方法的执行就是创造返回结果信号,将block_N传给didSubscribe()。

didSubscribe()将在racSingal_A.subscribeNext:时触发:

racSingal_A.subscribeNext

1.定义block

1)completeSignal()(忽略) 2)addSignal() (addSignal(racSingal_B);为racSingal_B添加subscribeNext:block_Y();

blockY:调用racSingal_A的sendNext)

2.将block()运行并获取返回值RACSignalBindBlock();

3.为当前bind方法的调用者添加subscribeNext:block_X();

(block_X实现:触发RACSignalBindBlock(x)并获得返回信号racSingal_B;

x为bind调用者的实参;)

subject.sendnext(x)

subject.sendnext(x)->subject.block_X(x)->RACSignalBindBlock(X)(中转暴露,可修改传参)->racSingal_B=[RACReturnSignal return:value];->addSignal(racSingal_B)->[racSingal_B subscribeNext:block_Y()  error:nil completed:nil]-> [RACReturnSignal subscribe:o]->[subscriber sendNext:self.value];->racSingal_B.next()->racSingal_A.sendNext

bind

flattenMap:

他内部其实就是实现了一个bind,flatten的block与内部bind的入参跟返回完全一样,同样没做处理。所以他的功能就是bind的功能。

map:

他内部其实就是实现了一个flattenMap,map:的入参是一个(id(^)(idvalue))block类型,map方法把这个block的返回值id处理成当前信号类类型并把处理过的block传进flattenMap入参,省掉了使用者在block中封装信号的代码。

组合:

concat:

通过concat:函数连接两个信号,将生成一个新信号,订阅新信号会立即触发信号1的

- (RACDisposable*)subscribeNext:(void(^)(idx))nextBlock error:(void(^)(NSError*error))errorBlock completed:(void(^)(void))completedBlock;

为信号1的订阅者生成  nextBlock,errorBlock,completedBlock;

继而调用信号1的didSubscribe(subscriber);

若信号1didSubscribe中有sendnext:则触发信号1的nextblock();继而触发新信号的nextblock;

信号1的订阅者调用sendCompleted方法时,会调用completedBlock(),触发信号2调用subscribe:,传参为信号1的订阅者,此时调用信号2的didSubscribe(subscriber),

若信号2didSubscribe中有sendnext:则触发信号1的nextblock();继而触发新信号的nextblock;

then:

内部封装的concat:通过filter:^(id_) {

return NO;

}返回A flattenMap: empty block的新信号,新信号由于addSignal()入参为空导致新信号subscriber.sendnext()不能被触发;

现象,第一个信号不返回,只返回第二个信号;

merge:

本质上还是利用了bind:

merge:返回组合信号的bind值,以下称信号fA&B,组合信号称信号A&B;

订阅 fA&B 时,触发bind内部的self subscribeNext:   A&B订阅,触发merge:中的遍历,传参subscriber为 A&B的订阅者,依此触发[subscriber sendNext: signal];执行bind中A&B的nextBlock,传入子信号A或B,执行addSignal(signal),为子信号订阅事件 [subscriber sendNext:x];(即fA&B发送信号),此时,当子信号发送消息时,fA&B可以响应。

zipWith:

这个最简单,zipwith:返回新信号,新信号被订阅时生成sendCompletedIfNecessary与sendNext的 block,同时两个原始信号被订阅,订阅逻辑都是数组添加信号返回值,并通过sendNext()判断是否两个信号都有返回,若都返回,则新信号发送消息,结果为两信号的元组。

combineLatest:reduce:

这个不太想写细节了,主要是用combineLatest组合成返回元组的新信号(combineLatestWith:订阅每个原始信号以监听),然后在reduceEach:中绑定传入的block使每次调用都触发;

其他API:

filter:   

此方法返回一个入参为bool类型,返回新信号,当满足bool条件时,才会收到信号内容。

ignore:

此方法输入一个发送值,或者输入ignoreValues,生成新信号,表示新信号会忽略输入的发送值发送;

take:

此方法输入数字,表示新生成的信号发送次数上限,超过次数的发送会被忽略;

takeLast:

此方法输入数字,表示新生成信号最后几次的值会被正常发送,前面发送的值会被发送,需要与sendCompleted一起使用;

takeUntil:

此方法输入一个信号,当输入信号sendCompleted或发送过一次后,新信号将忽略旧信号发送值;

distinctUntilChanged

当旧信号发送的值与上一次相异时,新信号才能收到值;

skip:

此方法输入数字,表示新生成信号会跳过旧信号前几次发送的值;

上一篇下一篇

猜你喜欢

热点阅读