美文网首页
RACDelegateProxy和RACCommand

RACDelegateProxy和RACCommand

作者: boy丿log | 来源:发表于2019-04-10 15:36 被阅读0次

    RACDelegateProxy

    用来实现代理,使用,将代理设置成RACDelegateProxy对象,并将RACDelegateProxy的rac_proxiedDelegate设置成之前的代理。

    RACDelegateProxy *pro = [[RACDelegateProxy alloc] initWithProtocol:@protocol(UITableViewDelegate)];
        [[pro rac_signalForSelector:@selector(tableView:didSelectRowAtIndexPath:)] subscribeNext:^(RACTuple * _Nullable x) {
            NSLog(@"%@",x.second);
        }];
        _aav = pro;
        pro.rac_proxiedDelegate = self;
        self.tableView.delegate = pro;
    

    RACCommand

    初始化

    - (instancetype)initWithSignalBlock:(RACSignal<id> * (^)(id input))signalBlock
    - (instancetype)initWithEnabled:(RACSignal *)enabledSignal signalBlock:(RACSignal<id> * (^)(id input))signalBlock
    

    上面的方法是调用下面的方法,不过传的值为nil

        //创建两个热信号,copy传入的block
       _addedExecutionSignalsSubject = [RACSubject new];
        _allowsConcurrentExecutionSubject = [RACSubject new];
        _signalBlock = [signalBlock copy];
    

    _executionSignals

    _executionSignals = [[[self.addedExecutionSignalsSubject
            map:^(RACSignal *signal) {
                return [signal catchTo:[RACSignal empty]];
            }]
            deliverOn:RACScheduler.mainThreadScheduler]
            setNameWithFormat:@"%@ -executionSignals", self];
    

    主要用来事件处理,执行的信号订阅添加执行的信号,接收的x是一个signal,并且在signal发送失败时转发为empty。在主线程上执行。

    _errors

    RACMulticastConnection *errorsConnection = [[[self.addedExecutionSignalsSubject
            flattenMap:^(RACSignal *signal) {
                return [[signal
                    ignoreValues]
                    catch:^(NSError *error) {
                        return [RACSignal return:error];
                    }];
            }]
            deliverOn:RACScheduler.mainThreadScheduler]
            publish];
            
        RACMulticastConnection *errorsConnection = [[[self.addedExecutionSignalsSubject
            flattenMap:^(RACSignal *signal) {
                return [[signal
                    ignoreValues]
                    catch:^(NSError *error) {
                        return [RACSignal return:error];
                    }];
            }]
            deliverOn:RACScheduler.mainThreadScheduler]
            publish];
        
        _errors = [errorsConnection.signal setNameWithFormat:@"%@ -errors", self];
        [errorsConnection connect];
    

    错误信号只捕获失败信号,并发送给订阅者,并转换为热信号。在主线程中执行。

    immediateExecuting

    _errors = [errorsConnection.signal setNameWithFormat:@"%@ -errors", self];
        [errorsConnection connect];
    
        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];
    
    

    这段代码可以这样分析:

    1.分析对接受的信号的处理:

    return [[[signal
                    catchTo:[RACSignal empty]]
                    then:^{
                        return [RACSignal return:@-1];
                    }]
                    startWith:@1];
    

    (1)当信号发送错误信号的时候,转发信号为空信号

    [signal
                    catchTo:[RACSignal empty]]
    

    (2)忽略信号所有发送的值,并在发送完成后返回一个-1值

    [signal then:^{
                        return [RACSignal return:@-1];
                    }]]
    

    (3)先订阅一个返回值为1的信号

    [signal startWith:@1]
    

    这段代码结合起来,就是,订阅这个信号的时候,
    1️⃣原信号如果发送失败的值得话会被转化为完成信号
    2️⃣原信号如果发送其他值的化,都不接受,如果收到完成值,会在订阅信号执行完之后执行一个-1回调
    3️⃣在执行信号之前,先执行一个1的回调

    总结:若信号发送完成,则一共会调用一次1值和-1值,失败的话只发送1值,其他的不做处理

    2.分析外围:

    经过信号的转变,再进一步对获取的信号进行处理

    (1)累加处理,没接收一次信号,就返回接收到的所有值的和

    [signal scanWithStart:@0 reduce:^(NSNumber *running, NSNumber *next) {
                return @(running.integerValue + next.integerValue);
            }]
    

    (2)如果返回的一个bool值,是否大于0

    [signal map:^(NSNumber *count) {
                return @(count.integerValue > 0);
            }]
    

    (3)在接受到信号的时候先执行一个0信号

    [signal startWith:@NO]
    

    immediateExecuting信号只会在发送完成和失败的时候才会调用:会给订阅者发送三个值:0,1,0,未完成的只会发送0,1

    _executing

    _executing = [[[[[immediateExecuting
            deliverOn:RACScheduler.mainThreadScheduler]//在主线程中运行
            // This is useful before the first value arrives on the main thread.
            startWith:@NO]//刚上发送一个0
            distinctUntilChanged]//除非有所改变否则不发送
            replayLast]//记录上一个发送的信号,当有新的订阅者的时候,直接发送上一个的值
            setNameWithFormat:@"%@ -executing", self];
    

    moreExecutionsAllowed

    RACSignal *moreExecutionsAllowed = [RACSignal
            if:[self.allowsConcurrentExecutionSubject startWith:@NO]
            then:[RACSignal return:@YES]
            else:[immediateExecuting not]];
    

    如果allowsConcurrentExecutionSubject发送的是YES的话订阅前面的signal,如果不是的话订阅的是后面的signal,这个signal的意思其实很明确,就是判断当前可不可以执行,如果可以,返回yes,如果不可以返回,当前是否在执行中。

    enabledSignal

    if (enabledSignal == nil) {
        enabledSignal = [RACSignal return:@YES];
    } else {
        enabledSignal = [enabledSignal startWith:@YES];
    }
        
    

    有没有传入判断是否可以执行操作的判断,如果有,则先执行以下yes,在执行enableSignal,
    否则一直返回yes。

    _immediateEnabled

        _immediateEnabled = [[[[RACSignal
            combineLatest:@[ enabledSignal, moreExecutionsAllowed ]]//合并两个信号,返回的值是个两元元组
            and]//两个值是否同时大于0
            takeUntil:self.rac_willDeallocSignal]
            replayLast];
    

    这个用来判断是否可以执行点击操作

    _enabled

    _enabled = [[[[[self.immediateEnabled
            take:1]
            concat:[[self.immediateEnabled skip:1] deliverOn:RACScheduler.mainThreadScheduler]]
            distinctUntilChanged]
            replayLast]
            setNameWithFormat:@"%@ -enabled", self];
    

    同上。

    BOOL enabled = [[self.immediateEnabled first] boolValue];
        if (!enabled) {
            NSError *error = [NSError errorWithDomain:RACCommandErrorDomain code:RACCommandErrorNotEnabled userInfo:@{
                NSLocalizedDescriptionKey: NSLocalizedString(@"The command is disabled and cannot be executed", nil),
                RACUnderlyingCommandErrorKey: self
            }];
    
            return [RACSignal error:error];
        }
    
        RACSignal *signal = self.signalBlock(input);
        NSCAssert(signal != nil, @"nil signal returned from signal block for value: %@", input);
    
        // We subscribe to the signal on the main thread so that it occurs _after_
        // -addActiveExecutionSignal: completes below.
        //
        // This means that `executing` and `enabled` will send updated values before
        // the signal actually starts performing work.
        RACMulticastConnection *connection = [[signal
            subscribeOn:RACScheduler.mainThreadScheduler]
            multicast:[RACReplaySubject subject]];
        
        [self.addedExecutionSignalsSubject sendNext:connection.signal];
    
        [connection connect];
        return [connection.signal setNameWithFormat:@"%@ -execute: %@", self, RACDescription(input)];
    

    每次执行后,会根据input返回一个信号,然后self.addedExecutionSignalsSubject会发送这个信号,来执行上面的流程。

    再来看下头文件我们可知:

    //用来获取需要订阅的信号
    @property (nonatomic, strong, readonly) RACSignal<RACSignal<ValueType> *> *executionSignals;
    //获取执行的状态
    @property (nonatomic, strong, readonly) RACSignal<NSNumber *> *executing;
    
    //是否可执行
    @property (nonatomic, strong, readonly) RACSignal<NSNumber *> *enabled;
    //失败时发送的信号
    @property (nonatomic, strong, readonly) RACSignal<NSError *> *errors;
    //是否允许执行多次
    @property (atomic, assign) BOOL allowsConcurrentExecution;
    
    //让executionSignals动发送一次信号
    - (RACSignal<ValueType> *)execute:(nullable InputType)input;
    
    

    相关文章

      网友评论

          本文标题:RACDelegateProxy和RACCommand

          本文链接:https://www.haomeiwen.com/subject/bxtoiqtx.html