RACCommand: NSObject
RACCommand
继承自NSObject
用于管理RACSignal
信号
RACCommand使用示例
RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id _Nullable input) {
return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
NSInteger integer = [input integerValue];
for (NSInteger i = 0; i < integer; i++) {
[subscriber sendNext:@(i)];
}
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
NSLog(@"信号销毁了");
}];
}];
}];
[[command.executionSignals switchToLatest] subscribeNext:^(id _Nullable x) {
NSLog(@"收到消息---%@",x);
} error:^(NSError * _Nullable error) {
NSLog(@"error了");
} completed:^{
NSLog(@"completed了");
}];
[command execute:@1];
[RACScheduler.mainThreadScheduler afterDelay:0.1
schedule:^{
[command execute:@2];
}];
[RACScheduler.mainThreadScheduler afterDelay:0.2
schedule:^{
[command execute:@3];
}];
//log结果
收到消息---0
信号销毁了
收到消息---0
收到消息---1
信号销毁了
收到消息---0
收到消息---1
收到消息---2
信号销毁了
completed了
- 通过
switchToLatest
方法来获取信号中的信号 - 因为默认情况下
RACCommand
是不支持并发操作的,需要在上次命令发送完成后,再发送下次信号
@property (nonatomic, strong, readonly) RACSignal<RACSignal<ValueType> *> *executionSignals;
通过以上示例可以看出整个流程中,传入一个block,这个block通过传入值生成对应的signal
, 而command属性executionSignals
即为这些信号的信号
通过 execute
方法 出入值
RACCommand
在Command
内部 是由几个很重要的信号组成的
初始化
初始化方法需要传入signalBlock
, 该block通过input传入值 生成一个RACSignal
在初始化方法中初始化了重要的信号
RACCommand initWithEnabled:(RACSignal *)enabledSignal signalBlock:(RACSignal<id> * (^)(id input))signalBlock {
_addedExecutionSignalsSubject = [RACSubject new];
_allowsConcurrentExecutionSubject = [RACSubject new];
_signalBlock = [signalBlock copy];
_executionSignals =...
_errors = ...
_executing = ...
_immediateEnabled = ...
_enabled = ...
}
addedExecutionSignalsSubject
addedExecutionSignalsSubject
即为包含信号的信号 当传入值时通过signalblock生成的signal即包含在改信号中
addedExecutionSignalsSubject
信号在execute:
执行时,对信号进行订阅和发送
- (RACSignal *)execute:(id)input {
BOOL enabled = [[self.immediateEnabled first] boolValue];
if (!enabled) {
return [RACSignal error:error];
}
RACSignal *signal = self.signalBlock(input);
//订阅信号
RACMulticastConnection *connection = [[signal
subscribeOn:RACScheduler.mainThreadScheduler]
multicast:[RACReplaySubject subject]];
//发送信号
[self.addedExecutionSignalsSubject sendNext:connection.signal];
[connection connect];
return connection.signal;
}
immediateExecuting && _executing 表示当前有操作执行的信号
immediateExecuting的逻辑是:
1. catchTo
捕获addedExecutionSignalsSubject
信号中的error信号,转换为empty
2. flattenMap:
将每个信号的开始和结束时间点转为1和-1信号(start为1 then为-1
)
3. scanWithStart:@0 reduce:
将上一步得到的1和-1进行叠加得到0 或者 非0
1. map:
将0/非0 转为 NO/YES 表示当前是否有信号正在处理
RACSignal *immediateExecuting = [[[[self.addedExecutionSignalsSubject
flattenMap:^(RACSignal *signal) {
return [[[signal
catchTo:[RACSignal empty]]
then:^{
return [RACSignal return:@-1];
}]
startWith:@1];
}]
scanWithStart:@0 reduce:^(NSNumber *running, NSNumber *next) {
return @(running.integerValue + next.integerValue);
}]
map:^(NSNumber *count) {
return @(count.integerValue > 0);
}]
startWith:@NO];
将immediateExecuting 信号进行优化 表示当前是否有任务执行
_executing = [[[[immediateExecuting
deliverOn:RACScheduler.mainThreadScheduler]
// This is useful before the first value arrives on the main thread.
startWith:@NO]
distinctUntilChanged]
replayLast]
moreExecutionsAllowed 表示是否允许更多信号执行
简单来看就是 当不允许并发时(默认不允许并发),[immediateExecuting not]
RACSignal *moreExecutionsAllowed = [RACSignal
if:[self.allowsConcurrentExecutionSubject startWith:@NO]
then:[RACSignal return:@YES]
else:[immediateExecuting not]];
executionSignals
@property (nonatomic, strong, readonly) RACSignal<RACSignal<ValueType> *> *executionSignals;
executionSignals
是一个包含信号的信号
executionSignals 只是简单的将self.addedExecutionSignalsSubject
信号中的所有错误信号NSError
转换为了empty
信号
_executionSignals = [[self.addedExecutionSignalsSubject
map:^(RACSignal *signal) {
return [signal catchTo:[RACSignal empty]];
}]
deliverOn:RACScheduler.mainThreadScheduler]
_enabled 信号 表示当前命令是否可以被再次执行
RACSignal *enabledSignal = [RACSignal return:@YES];
_immediateEnabled = [[[[RACSignal
combineLatest:@[ enabledSignal, moreExecutionsAllowed ]]
and]
takeUntil:self.rac_willDeallocSignal]
replayLast];
//保证信号中的第一个值在订阅线程,而其他值在主线程派发
_enabled = [[[[self.immediateEnabled
take:1]
concat:[[self.immediateEnabled skip:1] deliverOn:RACScheduler.mainThreadScheduler]]
distinctUntilChanged]
replayLast]