RAC(ReactiveCocoa)介绍(一)
最近在学习RAC,之前在iOS工作中,类之间的传值,无非是block、delegate代理、KVO和Notification等这几种方法。在RAC中,同样具备替代block、delegate代理、KVO和Notification,UI target、定时器timer、数据结构等各种方式。依靠FRP(响应式函数编程),RAC方法本身更加简单明了,通过提供信号的方式(RACSignal)可以捕捉到当前以及未来的属性值的变化,而且无需持续观察和更新代码。可直接在block中将逻辑代码加入其中,使得代码紧凑,更加直观。
先来介绍ObjC版本,使用cocoaPods在podfile中添加 pod 'ReactiveObjC', '~> 3.1.0' ,然后pod install一下。在项目中#import <ReactiveObjC.h>,建议放入pch头文件中。
通过RAC提供的方法与系统提供的方法分别进行对比,先来感受下RAC的强大之处
一、UIButton
1.1 传统方式
- (UIButton *)testBtn{
if (!_testBtn) {
_testBtn = [UIButton buttonWithType:UIButtonTypeCustom];
_testBtn.backgroundColor = [UIColor redColor];
_testBtn.frame = CGRectMake((UIScreen.mainScreen.bounds.size.width - )/, (UIScreen.mainScreen.bounds.size.height - )/, , );
[_testBtn addTarget:self action:@selector(tapAction) forControlEvents:UIControlEventTouchUpInside];
}
return _testBtn;
}
- (void)tapAction{
NSLog(@"你好");
}
运行结果为

1.2 RAC
- (void)btnRAC{
[[self.testBtn rac_signalForControlEvents:UIControlEventTouchUpInside]subscribeNext:^(__kindof UIControl * _Nullable x) {
NSLog(@"RAC按钮点击了");
}];
}
运行结果如下:

二、KVO
2.1 传统KVO
- (void)KVO{
[self orignKVO];
[self RACKVO];
}
- (void)orignKVO{
[self.testLabel addObserver:self forKeyPath:@"text" options:NSKeyValueObservingOptionNew context:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
if ([keyPath isEqualToString:@"text"] && object == self.testLabel) {
NSLog(@"%@",change);
}
}
2.2 RAC版
在使用RAC代替KVO时,不仅能大大增加代码可读性,而且RACObserve(<#TARGET#>, <#KEYPATH#>)宏定义中keyPath可以代码提示出target中的属性成员变量,降低手写代码错误的可能性。
[RACObserve(self.testLabel, text)subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
三、delegate代理
以UITextField为例,当需要对UITextField逻辑处理时,往往需要实现其各类代理方法,大大增加了代码量。当使用RAC之后
- (void)KVODelegate{
[[self rac_signalForSelector:@selector(textFieldDidBeginEditing:)fromProtocol:@protocol(UITextFieldDelegate)] subscribeNext:^(RACTuple * _Nullable x) {
NSLog(@"%@",x);
}];
self.textField.delegate = self;
}
@selector方法选择器中键入要实现的代理方法,代理名称声明为对应的代理名称。block代码块中,当触发监听的代理方法时返回元组类型数据,与swift中的元组类型有所区别,此处的元组看起来更像是数组。
四、Notification通知
- (void)RACNotification{
[[[NSNotificationCenter defaultCenter]rac_addObserverForName:UIKeyboardDidHideNotification object:nil]subscribeNext:^(NSNotification * _Nullable x) {
NSLog(@"%@",x);
}];
}
五、定时器timer
- (void)RACTimer{
//主线程每两秒执行一次
[[RACSignal interval:2.0 onScheduler:[RACScheduler mainThreadScheduler]]subscribeNext:^(NSDate * _Nullable x) {
NSLog(@"%@",x);
}];
//创建一个新线程
[[RACSignal interval: onScheduler:[RACScheduler schedulerWithPriority:(RACSchedulerPriorityHigh)name:@"com.reactiveCocoa.RACScheduler.mainTreadScheduler"]]subscribeNext:^(NSDate * _Nullable x) {
NSLog(@"%@",[NSThread currentThread]);
}];
}
六、数组与字典
- (void)RACSequence{
NSArray *array = @[@"乔布斯",@"苹果",@"发达"];
[array.rac_sequence.signal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
NSDictionary *dict = @{@"name":@"dragon",@"type":@"fire"};
[dict.rac_sequence.signal subscribeNext:^(id _Nullable x) {
RACTwoTuple *tuple = (RACTwoTuple *)x;
NSLog(@"key == %@, value == %@",tuple[],tuple[]);
}];
}
七、RAC使用基本流程
RAC基本使用方法与流程
- (void)RACBaseUse{
//RAC基本使用
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
[subscriber sendNext:@"sendOneMessage"];
//发送error信号
NSError *error = [NSError errorWithDomain:NSURLErrorDomain code: userInfo:@{@"errorMsg":@"this is a error message"}];
[subscriber sendError:error];
//4. 销毁信号
return [RACDisposable disposableWithBlock:^{
NSLog(@"signal已销毁");
}];
}];
//2.1 订阅信号
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
//2.2 针对实际中可能出现的逻辑错误,RAC提供了订阅error信号
[signal subscribeError:^(NSError * _Nullable error) {
NSLog(@"%@",error);
}];
}
以上代码中,subscribeNext作用为订阅信号,可在该block中输入逻辑相关代码块。
注意问题,可能也会有循环引用问题产生,如下:
- (void)RACFilter{
@weakify(self);
[[self.textField.rac_textSignal filter:^BOOL(NSString * _Nullable value) {
//过滤判断条件
@strongify(self)
if (self.textField.text.length >= ) {
self.textField.text = [self.textField.text substringToIndex:];
self.testLabel.text = @"已经到6位了";
self.testLabel.textColor = [UIColor redColor];
}
return value.length <= ;
}] subscribeNext:^(NSString * _Nullable x) {
//订阅逻辑区域
NSLog(@"filter过滤后的订阅内容:%@",x);
}];
}
以此来避免出现block的循环引用。
稍后会在后续的文章里继续介绍如何使用,以及RAC信号流程原理。demo代码放到GitHub上。
RAC(ReactiveCocoa)介绍(一)的更多相关文章
- RAC(ReactiveCocoa)使用方法(一)
RAC(ReactiveCocoa)使用方法(一) RAC(ReactiveCocoa)使用方法(二) 什么是RAC? 最近回顾了一下ReactiveCocoa的方法,也看了一些人的文章,现写篇文章总 ...
- RAC(ReactiveCocoa)使用方法(二)
RAC(ReactiveCocoa)使用方法(一) RAC(ReactiveCocoa)使用方法(二) 上篇文章:RAC(ReactiveCocoa)使用方法(一) 中主要介绍了一些RAC中常见类的用 ...
- RAC(ReactiveCocoa)概括
ReactiveCocoa(简称RAC,以下都用RAC)是github团队开源的一套基于Cocoa并且具有FRP(Functional Reactive Programming-响应式编程)特性的框架 ...
- ReactiveCocoa基础知识内容
本文记录一些关于学习ReactiveCocoa基础知识内容,对于ReactiveCocoa相关的概念如果不了解可以网上搜索:RACSignal有很多方法可以来订阅不同的事件类型,ReactiveCoc ...
- 关于Oracle的rac集群和mysql Galera Cluster的想法
到了新公司,公司用的是rac,我比较熟悉mysql第三方的集群方案Galera Cluster这类多主集群, 下面是我参考了他人对rac的介绍,然后和mysql方案进行的臆测级别的分析对比. rac和 ...
- oracle rac 学习(转载)
一. RAC 并发 RAC 的本质是一个数据库,运行在多台计算机上的数据库,它的主要任务是数据库就是事务处理,它通过 Distributed Lock Management(DLM:分布式锁管理器) ...
- [干货分享]一篇可能会让你爱上MVVM与ReactiveCocoa的文章
概要 在此工程中,本文将讨论将MVC改造为MVVM需要的一些基本方法,同时会适当穿插部分关于MVVM概念性的讨论!本文最大的意义在于,提供了一种读者可以复现的方式,逐步引出从MVC向MVVM尽可能平滑 ...
- 李洪强iOS经典面试题下
李洪强iOS经典面试题下 21. 下面的代码输出什么? @implementation Son : Father - (id)init { self = [super init]; if (self) ...
- iOS学习笔记39-ReactiveCocoa入门
FRP,全称为Functional Reactive Programming,是一种响应变化的编程范式,最近几年比较火,大概的理解就像这样: 当a的值或者b的值发生变化时,c的值会自动响应a的值或b的 ...
随机推荐
- 虚拟机console基础环境配置——sshd安全登陆
1. 概述2. 配置console的登陆2.1 配置sshd服务2.2 重启sshd服务2.3 无法登陆的问题解决3. 配置密钥登陆3.1 上传公钥的方式3.2 下载密码的方式3.3 虚拟机和宿主机共 ...
- java.lang.ClassNotFoundException: com.mysql.jdbc.Drive
Linux下使用eclipse开发web项目,运行的时候出现 Java.lang.ClassNotFoundException: com.MySQL.jdbc.Driver,解决办法如下: 1.导入M ...
- python——在文件存放路径下自动创建文件夹!
1.a.py文件存放的路径下为(D:\Auto\eclipse\workspace\Testhtml\Test) 2.通过os.getcwd()获取的路径为:D:\Auto\eclipse\works ...
- 【BAT面试题系列】面试官:你了解乐观锁和悲观锁吗?
前言 乐观锁和悲观锁问题,是出现频率比较高的面试题.本文将由浅入深,逐步介绍它们的基本概念.实现方式(含实例).适用场景,以及可能遇到的面试官追问,希望能够帮助你打动面试官. 目录 一.基本概念 二. ...
- OsharpNS轻量级.net core快速开发框架简明入门教程-代码生成器的使用
OsharpNS轻量级.net core快速开发框架简明入门教程 教程目录 从零开始启动Osharp 1.1. 使用OsharpNS项目模板创建项目 1.2. 配置数据库连接串并启动项目 1.3. O ...
- 【STM32H7教程】第11章 STM32H7移植SEGGER的硬件异常分析
完整教程下载地址:http://forum.armfly.com/forum.php?mod=viewthread&tid=86980 第11章 STM32H7移植SEGGER的硬 ...
- go语言视频教程和电子书下载
golang视频教程: https://noxue.com/p/399809259943301 go语言 pdf电子书: Design Pattern In Go[go语言设计模式].pdf Go P ...
- 将本地文件传输到GitHub
统一概念: 工作区:增删文件和内容 暂存区:键入命令 git add 改动的文件,此次改动就放到了 『暂存区』 本地仓库 :键入命令 git commit ,此次改动就放到了『本地仓库』,每个 com ...
- Linux创建普通用户
声明:作者原创,转载注明出处. 作者:帅气陈吃苹果 1.创建用户,-m表示同时创建用户家目录 sudo useradd -m hadoop 2.为创建的hadoop用户设置密码 sudo passwd ...
- uni-app—从安装到卸载
uni-app实现了一套代码,同时运行到多个平台.支持iOS模拟器.Android模拟器.H5.微信开发者工具.支付宝小程序Studio.百度开发者工具.字节跳动开发者工具 工具安装 开发uni-ap ...