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的 ...
随机推荐
- CAN总线、自然与人
最近在研究CAN总线,发现CAN总线的CANH和CANL上的波形有好有坏,如图1所示红框中所示,有的波形有明显的过冲,想弄清楚原因,请教了一些前辈,自己也查阅了一些资料,但由于孔丙火(微信公众号:孔丙 ...
- .net中的线程同步基础(搬运自CLR via C#)
线程安全 此类型的所有公共静态(Visual Basic 中为 Shared)成员对多线程操作而言都是安全的.但不保证任何实例成员是线程安全的. 在MSDN上经常会看到这样一句话.表示如果程序中有n个 ...
- 优化:mysql查询最近一条记录
下策--查询出结果后将时间排序后取第一条 select * from a where create_time<="2017-03-29 19:30:36" order by ...
- MYSQL——数据库存储引擎!
本人安装mysql版本为:mysql Ver 14.14 Distrib 5.7.18, for Win64 (x86_64),查看mysql的版本号方式:cmd-->mysql --vers ...
- 机器学习中的范数规则化-L0,L1和L2范式(转载)
机器学习中的范数规则化之(一)L0.L1与L2范数 zouxy09@qq.com http://blog.csdn.net/zouxy09 今天我们聊聊机器学习中出现的非常频繁的问题:过拟合与规则化. ...
- 死磕 java集合之DelayQueue源码分析
问题 (1)DelayQueue是阻塞队列吗? (2)DelayQueue的实现方式? (3)DelayQueue主要用于什么场景? 简介 DelayQueue是java并发包下的延时阻塞队列,常用于 ...
- 带你由浅入深探索webpack4(一)
相信你或多或少也听说过webpack.gulp等这些前端构建工具.近年来webpack越来越火,可以说成为了前端开发者必备的工具.如果你有接触过vue或者react项目,我想你应该对它有所了解. 这几 ...
- Protocol Buffers(1):序列化、编译与使用
目录 序列化与反序列化 Protocol Buffers概览 Protocol Buffers C++ 编译 Protocol Buffers C++ 使用 Protocol Buffers的可读性 ...
- [翻译 EF Core in Action 1.6]你的第一个EF Core应用程序
Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...
- 关于vue使用form上传文件
在vue中使用form表单上传文件文件的时候出现了一些问题,获取文件的时候一直返回null, 解决之后又出现发送到后台的file文件后台显示为空,解决源码 <template> <d ...