前言

学习 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. 见识浅薄,如有疑惑,欢迎交流,求吐槽,求成长。

#RAC #RACCommand

RACCommand 粗解相关推荐

  1. C++ 实现 STL 标准库和算法(二)template 编程和迭代器粗解 实验楼笔记

    一.template 编程和迭代器粗解 1.1 实验内容 本节内容主要讲述 c++11 模板的用法,以后的代码中会大量的用到模板的知识.同时简单讲解迭代器的相关知识,为后面容器和算法的内容作铺垫. 1 ...

  2. Anaconda安装教程粗解

    Anaconda安装教程&粗解 一.anaconda下载 二.anaconda安装 三.anaconda粗解 1.anaconda简介 2.版本特点 3.常见问题 4.anaconda优点 四 ...

  3. node binding.gyp 配置文件粗解

    我感觉谷歌的官方文档本身就不完善,导致我没办法详解,很多配置都是看 别人写的 慢慢摸索出来的.windows篇章里,我实现了一个海康node插件,linux版里,我同样实现了这个功能. {" ...

  4. 色调粗解(精问详背)

    色调粗解(精问详背) 一.总结 一句话总结:颜色的功能超级强大,要好好的看,认真的背. 1.暖色调颜色? 红色.橙色.黄色--为暖色,象征着:太阳.火焰. 2.冷色调颜色? 绿色.蓝色.紫色--为冷色 ...

  5. 【基础教程】法线贴图原理与制作 粗解

    现在用N渲IK渲啥的越来越多,不少人都在问法线贴图怎么做 这个教程就来讲讲法线贴图 完全没有相关基础可能看起来比较吃力 教程完之前不要插楼····· 简单说来法线贴图就是让低面模型也可以呈现出非常多的 ...

  6. Nginx配置文件粗解

    为什么80%的码农都做不了架构师?>>>    上一篇搭建了nginx+php基本环境,这一篇专门来学习nginx配置文件,以及怎样让nginx支持php,nginx的配置文件结构类 ...

  7. robotframwork接口测试(五)—接口分层测试粗解

    个人小结,仅供参考. 接口测试很简单,但是很重要. 可以写代码,也可以用工具进行测试.工具说说就很多了,简单介绍一下我目前用过的几个能够测试接口的工具, Burpsuite:这类偏请求攻击类软件 Fi ...

  8. 设备树和pinctrl粗解

    上次文章中 我以DS18b20为例,在设备树中定义了ds18b20的资源(device),当时是依葫芦画瓢,没有深入探究,本文主要探讨下pin在设备树中的描述 参考文章:Linux内核中的GPIO系统 ...

  9. 新能源汽车比亚迪唐220V放电系统粗解,以及为什么需要支持V2G?

    本篇文章想要系统的把传统汽车和新能源汽车的交流发电和V2H和V2G的功能梳理一下,全文主要分几个部分来分别介绍,在汽车使用中,一种能够将铅酸电池电压DC12V直流电转换(在新能源汽车里面就是用高压电源 ...

最新文章

  1. Reddit高赞:机器学习领域「八宗罪」!同行评审变味,盲目崇拜盛行
  2. perl脚本发送邮件
  3. 1024. 科学计数法 (20)
  4. mui app webview 沉浸式导航_AR实景导航 轻松找到网约车!高崎机场推出网约车专属上车区等便民举措...
  5. SQLServer 2000 生成数据源的SQL脚本
  6. Oracle新建用户并授权
  7. 初学Vue.js--数据绑定与文本插值
  8. C和指针之字符串实现strrstr函数
  9. 计算机背板知识,你知道背板的选购技巧吗?
  10. 在Centos7 更改Docker默认镜像和容器的位置
  11. 学3D建模,工作后薪资一般是多少
  12. Hibernate JPA中insert插入数据后自动执行select last_insert_id()解决方法
  13. PAT 1153 Decode Registration Card of PAT (25 分)- 甲级
  14. bzoj 4443: [Scoi2015]小凸玩矩阵(二分+二分匹配)
  15. 使用freemarker模板生成html文件(一)
  16. Ubuntu安装kaldi
  17. prince2 成功的项目管理_我的PRINCE2故事
  18. 修复Win10任务栏开始菜单等系统图标无法点击问题
  19. python音乐编程_可以编程写音乐的python库musicpy教程(第一期) musicpy的数据结构...
  20. 纯干货分享,2021年阿里巴巴社招面试题总结,本人上周已成功入职!

热门文章

  1. linux系统无法挂载U盘
  2. Linux课堂随笔---第四天
  3. 【spring 5】AOP:spring中对于AOP的的实现
  4. JavaScript Document
  5. va_start() va_end()函数应用
  6. SLAM学习,小白入门到殿堂级大牛资料整理
  7. linux下history(历史)命令用法详解
  8. webconfig加密
  9. 开机BIOS语言(转载)
  10. ASP.NET 学习历程