RAC - 点击获取验证码 demo

文章系列
《ReactiveCocoa 概述》
《RACSignal》
《RACDisposable》
《RACSubject、RACReplaySubject(内附冷信号和热信号的区别)》
《集合RACTuple、RACSequence》
《RAC 中的通知、代理、KVO, 基本事件、方法的监听》
《rac_liftSelector》
《RACMulticastConnection》
《RACCommand》
《RAC - 核心方法bind》
《RAC - 定时器》
《RACScheduler》
《RAC - 点击获取验证码 demo》
《RAC - 映射(Map & flattenMap)》
《RAC信号操作解释合集》
《RAC - 信号的生命周期》

思路分析:

  • 其实就是RACCommand 的使用
  • 第一个信号是一个做减一操作的计时器 -> countSignal
  • 第二个信号为phoneTextfield 的位数是否为11 位, 返回bool 值, 根据需要求可以在里面添加其他判断.
  • 通过RACCommandinitWithEnabled初始化方法, 将这两个信号作为参数, 进而来控制最终结果
- (void)fetchCodeTest {

    // 定义一个返回值类型为闭包的属性
    RACSignal *(^counterSignal)(NSNumber *count) = ^RACSignal * (NSNumber *count) {
        
        // 主线程 间隔一秒的定时器
        RACSignal *timerSignal = [RACSignal interval:1 onScheduler:RACScheduler.mainThreadScheduler];
        
        // scanWithStart 扫描操作, 对每次一信号值, 进行处理
        // count 为起始值, 也就是第一次的running
        // next 为信号值, 从时间早晚排序
        // running 为上一次的闭包中return 的结果.
        RACSignal *countSignal = [[timerSignal scanWithStart:count reduce:^id _Nullable(NSNumber *running, id next) {
            
            // 这里是每一秒减一, 因为是倒计时操作
            NSLog(@"scanWithStart中闭包操作:%zd-%@", running.integerValue, next);
            return @(running.integerValue - 1);
            
            // takeUntilBlock: 通过闭包内部操作 来控制外部信号, 也就是说,当闭包内部满足什么条件时, 闭包外部的信号就终止订阅
            // 返回yes的时候,停止信号的订阅
        }] takeUntilBlock:^BOOL(NSNumber *x) {
            return x.integerValue < 0;
        }];
        
        // startWith: 信号会首先发送一个值,这个信号结束, 下一个才开始, 一般都为初始值
        return [countSignal startWith:count];
    };
    
    // 监听输入框位数是否为11 位数的一个信号, 信号的结果为bool 类型
    RACSignal *enableSignal = [self.phoneTextfield.rac_textSignal map:^id _Nullable(NSString *value) {
        return @(value.length == 11);
    }];
    
    // 定义一个多信号管理工具
    RACCommand *command = [[RACCommand alloc] initWithEnabled:enableSignal signalBlock:^RACSignal * _Nonnull(id  _Nullable input) {
        return counterSignal(@10);
    }];
    
    // 原始信号必须是发送信号的信号(sendNext (RACSignal)…),发送的信号会被订阅,直到发送下一个信号,前一个被发送的信号就终止订阅,方法的作用是,每次订阅最新的信号。和map一起往往被认为是替代flattenMap的方案。
    RACSignal *counterStringSignal = [[command.executionSignals switchToLatest] map:^id _Nullable(NSNumber *value) {
        return [value stringValue];
    }];
    
    RACSignal *resetStringSignal = [[command.executing filter:^BOOL(NSNumber * _Nullable value) {
        return !value.boolValue;
    }] mapReplace:@"点击获取验证码"];
    
    [self.fetchCodeButton rac_liftSelector:@selector(setTitle:forState:) withSignals:[RACSignal merge:@[counterStringSignal, resetStringSignal]], [RACSignal return:@(UIControlStateNormal)], nil];
    
    // rac_liftSelector 就等价与下面注释掉的内容
//    [[RACSignal merge:@[counterStringSignal, resetStringSignal]] subscribeNext:^(id  _Nullable x) {
//        [self.fetchCodeButton setTitle:x forState:UIControlStateNormal];
//    }];
    
    self.fetchCodeButton.rac_command = command;
}

.End

你可能感兴趣的:(RAC - 点击获取验证码 demo)