当前位置: 首页 > 编程日记 > 正文

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


相关文章:

将整数拆分为2的幂次方

任意一个正整数都可以用2的幂次方表示&#xff0c;例如&#xff1a;137&#xff1d;2^72^32^0&#xff0c;同时约定次方用括号来表示&#xff0c;即a^b&#xff1d;a(b)。由此可知&#xff0c;137可表 示&#xff1a;2(7)2(3)2(0)。进一步&#xff1a;72^222^0(2^1用2表示)&…

vbs脚本在服务器上虚拟按键,iisvdir.vbs iis虚拟目录管理脚本使用介绍

IIS管理器也是通过调用iisvdir.vbs来实现虚拟目录的创建和删除的。我们可以通过命令行的方式来执行iisvdir.vbs脚本1)创建虚拟目录&#xff1a;cscript c:\windows\system32\iisvdir.vbs [/s server] [/u username /p password] /create [virtualRoot] Alias PhysicalPath2)删除…

Python字典部分源码分析,字典是无序的

1 def clear(self): # real signature unknown; restored from __doc__ 2 """ D.clear() -> None. Remove all items from D. """ 3 pass 1 #练习1、清空字典&#xff08;置空&#xff09; 2 li {"key1":"v…

【2011-3】【旋转表格】

Description 小敏是个数学迷&#xff0c;特别擅长加法与除法。老师给他一个问题&#xff0c;有一个22表格&#xff0c;表中有正整数A, B, C 和D&#xff0c;表格和表格值的计算如下&#xff1a;小敏的任务是对给出的表格每次顺时针旋转90度&#xff0c;使旋转后的表格值最大&am…

iOS-FXDanmaku弹幕库介绍、相关技术分享

前言 去年, 2016年, 一大波直播平台在移动端涌出, 直播慢慢步入了人们的视角. 网上如今能够看到各式各样的直播, 如秀场直播、游戏直播、体育直播、娱乐直播等等. 在各种类型的直播中, 弹幕在PC、移动端都几乎成为了标配, 今天在这里主要介绍一下个人开源的iOS弹幕, 以及提前为…

【廖雪峰Python学习笔记】字符串与编码

字符串与编码 三种字符编码 ASCII编码 &#xff1a;计算机由美国人发明&#xff0c;最早只有127个字符编码—— 大小写英文字母、数字和符号Unicode&#xff1a;把中文、日文、韩文等所有语言统一到一套编码中&#xff0c;2-4byte&#xff0c;现代OS和大多数语言都支持utf-8&a…

application

说明: 进行应用级操作.比如:设置提醒框,打开其他应用,显示联网状态,控制状态栏 单例对象, UIApplication *app[UIApplication sharedApplication];常用方法 方法1:设置app图标数字提示信息//设置app图标数字提示信息app.applicationIconBadgeNumber10;//ios8以后需要实现以下方…

博客园2013年4月份第2周源码发布详情

Silk Navigation for ASP.NET源码 2013-4-12 [VS2010]功能介绍&#xff1a;Silk Navigation 微软提供&#xff0c;为构建cross-browser 的Web应用程序&#xff0c;是用ASP.NET MVC3和jQuery的。它是非常简单使用ASP.NET Web窗体构建&#xff0c;从而在一个相当小的&#xff0c…

iOS 静态库封装

静态库和动态库 静态库和动态库存在形式 静态库&#xff1a;以.a 和 .framework为文件后缀名。动态库&#xff1a;以.tbd(之前叫.dylib) 和 .framework 为文件后缀名。 静态库和动态库的区别 静态库&#xff1a;链接时会被完整的复制到可执行文件中&#xff0c;被多次使用就有多…

【廖雪峰Python学习笔记】list tuple dict set

列表元组字典集合创建l [1, ‘a’, [1, 3], True]t (1, )d {‘key’ : ‘value’}s set([1, 2, 4, 2, 1])索引l[1]t[0]d.get(‘key’)/插入l.insert(1, ‘3’) / l.append(‘4’)/d[‘k1’] ‘v1’s.add(‘9’)修改l[0] 4/d[‘k1’] v/移除l.pop(0)/d.pop(‘k1’)s.remo…

响应式布局简明示例

响应式布局简明示例&#xff0c;响应式布局最好同时也是自适应布局&#xff0c;然后再配合css3媒体查询&#xff0c;来达到完美的响应式布局。css3的媒体查询ie9一下是不支持的&#xff0c;这太遗憾了&#xff0c;不过幸运的是有大神已经为前端屌丝们写好了用于IE9以下的媒体查…

iOS - APP任意push新页面那些事

大家都知道&#xff0c;UINavigationController对象有一个方法pushViewController&#xff0c;用来做视图跳转&#xff0c;也是在iOS开发中常用的页面转换方法之一。大多数APP的结构一般都是&#xff0c;使用一个UITabBarController&#xff0c;每个tab上都是一个UINavigationC…

主攻ASP.NET.4.5 MVC4.0之重生:Entity Framework生成实体类步骤(十三)

1.新建一个ASP.NET MVC 4.0 项目 2.安装Entity Framework Power Tools 3.Entity Framework- -RepositoryReverse Engineer Code First 4.Install-Package EntityFramework or Update-Package EntityFramework PM -Repository Install-Package EntityFramework 已安装“EntityFr…

【廖雪峰Python学习笔记】高阶函数

Higher-order function高阶函数映射过滤算法排序算法高阶函数 变量可指向函数 >>> abs # 函数 <built-in function abs> >>> abs(-0) # 函数调用 0 >>> func abs # 变量可指向函数 >>> func(-9) # 调用变量 调用函数 9函数名…

丁贵才130702010042第二次作业

第二次作业 2.9 设有如下语句&#xff0c;请用相应的谓词公式分别把它们表示出来&#xff1a; &#xff08;1&#xff09;有的人喜欢梅花&#xff0c;有的人喜欢菊花&#xff0c;有的人既喜欢梅花有喜欢梅花。 解&#xff1a;定义谓词 P&#xff08;x&#xff09;&#xff1a;x…

SpringMVC @RequestBody接收Json对象字符串

以前&#xff0c;一直以为在SpringMVC环境中&#xff0c;RequestBody接收的是一个Json对象&#xff0c;一直在调试代码都没有成功&#xff0c;后来发现&#xff0c;其实 RequestBody接收的是一个Json对象的字符串&#xff0c;而不是一个Json对象。然而在ajax请求往往传的都是Js…

【iOS】自定义日期选择器

自定义了一个日期选择器&#xff0c;与大家分享一下&#xff0c;期待宝贵建议。 github下载地址&#xff1a;https://github.com/huahua0809/XHDatePicker 下面只是说明一下怎么用&#xff0c;具体实现请下载代码看看&#xff1b; 如果大家觉得这个分享有所帮助的话&#xff0c…

【廖雪峰Python学习笔记】函数式编程

Functional Programming高阶函数返回函数匿名函数装饰器偏函数高阶函数 面向过程的程序设计&#xff1a; 把大段代码拆成函数&#xff0c;通过一层层函数调用&#xff0c;可将复杂任务分解成若干简单的任务函数是面向过程的程序设计的基本单位计算机Computer && 计算c…

asp 随机读取ID之Access

我在用ASP连接access 这个桌面数据库的时候&#xff0c;有时候要随机读取ID&#xff0c;传统的办法是&#xff1a; select top 3 * from tablename order by Rnd(ID) 但这样不行&#xff0c;默认还是按ID排序。 解决办法加上timer() 这个函数 select top 3 * from tablenam…

iOS Plist 文件的 增 删 改

一&#xff1a;Plist 文件的创建 Plist 文件作为我们IOS开发的一种数据存储文件&#xff0c;还是经常会用到的。在看《X-code江湖录》的时候&#xff0c;看到了这一点。自己就写了一下&#xff0c;把写的东西分享出来&#xff01;先看看它的创建&#xff0c;它的创建和我们其他…

Shine Button动画效果 类似Tinder APP的卡片界面

Shine Button动画效果--WCLShineButton 类似太阳动画的button FSPagerView 主要使用UICollectionView实现的优雅的屏幕幻灯片效果&#xff0c;主要用于Banner、产品展示、欢迎引导等。有Swift和OC两个版本。 folding-cell 一个可扩展的具有折叠效果的内容单元格 Cell折叠动效…

【廖雪峰Python学习笔记】面向对象编程OOP

面向对象编程 OOP&#xff1a;Object Oriented Programming程序的基本单元&#xff1a;对象 [ 数据 操作数据的函数] [属性 方法]三大特点&#xff1a;数据封装、继承和多态OPP中的计算机程序&#xff1a; 一系列命令的集合 —— 一组函数顺序执行。函数化大为小&#xff0…

基于 CoreText 实现的高性能 UITableView

来源&#xff1a;伯乐在线 - Hawk0620 如有好文章投稿&#xff0c;请点击 → 这里了解详情 如需转载&#xff0c;发送「转载」二字查看说明 引起UITableView卡顿比较常见的原因有cell的层级过多、cell中有触发离屏渲染的代码&#xff08;譬如&#xff1a;cornerRadius、maskTo…

.net程序员面试题

1&#xff0e; 在web页面中不论显示器的分辨率的大小是800600&#xff0c;还是1024768使得页面都显示在屏幕中间。 答&#xff1a;Margin:auto; 2&#xff0e; 请利用正则表达式验证一个字符串是否为数字串 &#xff08;请用csharp&#xff09;。 1 public static b…

Android深度探索与驱动开发(一)

Android移植可分为两个部分&#xff1a;应用移植和系统移植。应用移植是指将应用程序移植到某一特定硬件平台上。由于不同硬件平台之间的差异&#xff0c;Android SDK API也有可能存在差异&#xff0c;或者将应用程序从低版本Android移植到高版本的Android上。为了保证应用程序…

【廖雪峰Python学习笔记】面向对象高级编程

文章目录为实例和类绑定属性和方法\_\_slots__限制当前class实例&#xff0c;对子类不管用property装饰器&#xff0c;将getter方法变成属性多重继承 —— 一个子类可同时获得多个父类的所有功能[Mixin]定制类枚举类元类为实例和类绑定属性和方法 创建类 class Animal(object…

5分钟 搭建免费个人博客

五分钟倒数已经可以计时了。 三步完成免费个人博客搭建&#xff0c; 这是一篇小白也能看懂的文章&#xff0c;本文主要针对mac OS &#xff0c;Windows 除了软件安装方式和命令有些区别&#xff08;装了git bash也一样&#xff09;&#xff0c;其他基本一样。 你可能会经常看到…

基数排序之算法

一、定义基数排序是一种非比较型整数排序算法&#xff0c;其原理是将整数按位数切割成不同的数字&#xff0c;然后按每个位数分别比较。由于整数也可以表达字符串&#xff08;比如名字或日期&#xff09;和特定格式的浮点数&#xff0c;所以基数排序也不是只能使用于整数。二、…

MyBaties学习记录

typeAliases详解&#xff1a; 类型别名是为 Java 类型设置一个短的名字。它只和 XML 配置有关&#xff0c;存在的意义仅在于用来减少类完全限定名的冗余&#xff1b;&#xff08;也就是为类型设置简称&#xff09; 实例: 通过包名称加上简称调用代替&#xff1b; 注解表示: // …

【廖雪峰Python学习笔记】错误、调试、测试

文章目录错误处理调试单元测试unitcase文档测试错误类型程序编写问题bug – 字符类型错误等用户输入错误 – 输入不符合规定的字符串异常&#xff0c;程序运行时无法预测 – 磁盘满了&#xff0c;无法写 错误处理 错误处理机制&#xff1a;try…except…finally… try运行可…