RACCommand 粗解

前言

学习 RAC 的过程中,RACCommand 是我一直很迷惑的点,感觉一直抓不到它的要点,不明白为何要这样使用。曾经想过用别的方法来替代,只要能找到替代的方法,暂时就没必要死磕,结果发现避免不了,那就解决他。

实践

RACCommand 最常用于两个地方,监听按钮点击,网络请求

  1. 按钮点击,使用 RAC 有两种方式

    • UIControl+RACSignalSupport

                
                
      1
                
                
      - (RACSignal *)rac_signalForControlEvents: (UIControlEvents)controlEvents;
    • UIButton+RACCommandSupport

                
                
      1
                
                
      @ property (nonatomic, strong) RACCommand *rac_command;
  2. 第一种方式,也是我曾经想过替代 RACCommand 来处理按钮点击事件的方法

            
            
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
            
            
    // 按钮是否可点击
    RAC( self.commandBtn, enabled) = validSignal;
    [[[ self.commandBtn rac_signalForControlEvents: UIControlEventTouchUpInside]
    // flattenMap 生成新的信号,在信号中可以处理点击事件,并发送结果
    flattenMap:^RACStream *( id value) {
    return [ self btnClickSignal];
    }] subscribeNext:^( id x) {
    NSLog( @"====%@", x); // ====按钮点击了
    }];
    - (RACSignal *)btnClickSignal {
    return [RACSignal createSignal:^RACDisposable *( id<RACSubscriber> subscriber) {
    /**
    * 这里可以进行处理按钮点击后的事件,并把想要的结果传递出去
    */
    [subscriber sendNext: @"按钮点击了"];
    [subscriber sendCompleted];
    return nil;
    }];
    }
    • 上述就是根据 UIControl 的分类信息,进行处理按钮点击事件的第一种方式。但是有一个问题:

    • 你只有手动点击了按钮,并且是 UIControlEventTouchUpInside 的事件状态下才会执行 block 中的代码。

    • 如果需要主动触发事件呢,而在老代码中,可以手动调用 [self btnClick],所以就必须使用第二种方式,RACCommand
  3. RACCommand

    • 初始化赋值 rac_command

                
                
      1
      2
      3
      4
      5
      6
      7
      8
                
                
      // 初始化 command, enabled 表示按钮可否点击
      RACCommand *command = [[RACCommand alloc] initWithEnabled:validSignal
      signalBlock:^RACSignal *( id input) {
      return [ self btnClickSignal];
      }];
      self.commandBtn.rac_command = command;
    • 监听

      • executionSignals 是信号中的信号
      • 必须进行处理、转换,得到外层信号
      • 监听最外层的信号,才能获取到信号中的信息
                
                
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
                
                
      // 1. 监听信号中的信号
      [command.executionSignals subscribeNext:^( id x) {
      [x subscribeNext:^( id x) {
      NSLog( @"---%@", x);
      }];
      }];
      // 2. 使用 flattenMap 进行转换,返回最外层的信号
      [[command.executionSignals flattenMap:^RACStream *( id value) {
      return value;
      }] subscribeNext:^( id x) {
      NSLog( @"---%@", x);
      }];
      // 3. switchToLatest 获取最新的信号,专门用于处理 信号中的信号
      [command.executionSignals.switchToLatest subscribeNext:^( id x) {
      NSLog( @"---%@", x);
      }];
    • execute 执行

      • 这也就是解决第一种方式无法主动触发事件方法。
      • 相当于调用 [self btnClick]
                
                
      1
      2
      3
      4
      5
      6
      7
      8
                
                
      // 1. 返回的是 RACSignal,可以被订阅
      [command execute: nil];
      // 2. 只有手动 执行命令,才能监听到信号
      // 如果是 点击按钮, 这里是监听不到信息的
      [[command execute: nil] subscribeNext:^( id x) {
      NSLog( @"execute---%@", x);
      }];
    • executing 是否正在执行命令

                
                
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
                
                
      // executing 一开始就会监听一次,肯定是 0,一般会忽略(skip)一次
      // x 非 0 即 1,命令执行完毕/正在执行
      // 执行一次命令,block 中会调用两次,正在执行->执行完毕
      [[command.executing skip: 1] subscribeNext:^( id x) {
      if ([x integerValue] == 1) {
      NSLog( @"正在执行");
      } else {
      NSLog( @"执行完毕");
      }
      }];

结论

  1. 上述就是 RACCommand 在按钮点击事件中的处理,网络请求的话,代码几乎一致,流程都是一样的。在初始化 RACCommand 的内部,进行事件处理/网络请求,并把结果通过 subscriber 发送出去,外部通过订阅信号,就可以获取事件处理的结果,从而进行 UI 更新。

  2. RACCommand 本质上就是用来处理事件的,事件如何处理,事件中的数据如何传递,甚至事件的执行过程,都可以表现出来。

  3. 见识浅薄,如有疑惑,欢迎交流,求吐槽,求成长。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值