最近在学习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

KVO在使用时,必须在- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void*)context中实现针对KVO监听属性值变化的处理,而且对于KeyPath书写容易产生手写错误。在对应类dealloc时,KVO还必须要进行remove操作,否则会程序crash。
- (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上。

demo连接:https://github.com/zxy1829760/RAC-1-

RAC(ReactiveCocoa)介绍(一)的更多相关文章

  1. RAC(ReactiveCocoa)使用方法(一)

    RAC(ReactiveCocoa)使用方法(一) RAC(ReactiveCocoa)使用方法(二) 什么是RAC? 最近回顾了一下ReactiveCocoa的方法,也看了一些人的文章,现写篇文章总 ...

  2. RAC(ReactiveCocoa)使用方法(二)

    RAC(ReactiveCocoa)使用方法(一) RAC(ReactiveCocoa)使用方法(二) 上篇文章:RAC(ReactiveCocoa)使用方法(一) 中主要介绍了一些RAC中常见类的用 ...

  3. RAC(ReactiveCocoa)概括

    ReactiveCocoa(简称RAC,以下都用RAC)是github团队开源的一套基于Cocoa并且具有FRP(Functional Reactive Programming-响应式编程)特性的框架 ...

  4. ReactiveCocoa基础知识内容

    本文记录一些关于学习ReactiveCocoa基础知识内容,对于ReactiveCocoa相关的概念如果不了解可以网上搜索:RACSignal有很多方法可以来订阅不同的事件类型,ReactiveCoc ...

  5. 关于Oracle的rac集群和mysql Galera Cluster的想法

    到了新公司,公司用的是rac,我比较熟悉mysql第三方的集群方案Galera Cluster这类多主集群, 下面是我参考了他人对rac的介绍,然后和mysql方案进行的臆测级别的分析对比. rac和 ...

  6. oracle rac 学习(转载)

    一. RAC 并发 RAC 的本质是一个数据库,运行在多台计算机上的数据库,它的主要任务是数据库就是事务处理,它通过 Distributed Lock Management(DLM:分布式锁管理器)  ...

  7. [干货分享]一篇可能会让你爱上MVVM与ReactiveCocoa的文章

    概要 在此工程中,本文将讨论将MVC改造为MVVM需要的一些基本方法,同时会适当穿插部分关于MVVM概念性的讨论!本文最大的意义在于,提供了一种读者可以复现的方式,逐步引出从MVC向MVVM尽可能平滑 ...

  8. 李洪强iOS经典面试题下

    李洪强iOS经典面试题下 21. 下面的代码输出什么? @implementation Son : Father - (id)init { self = [super init]; if (self) ...

  9. iOS学习笔记39-ReactiveCocoa入门

    FRP,全称为Functional Reactive Programming,是一种响应变化的编程范式,最近几年比较火,大概的理解就像这样: 当a的值或者b的值发生变化时,c的值会自动响应a的值或b的 ...

随机推荐

  1. jquery实现登录加密的几种方法以及cookie存放加密/解密

    本篇文章的所有操作都是在jsp页面上进行的,完全与后台分离 part 1:加密方式 这个加密方式网上基本都有很多人总结,我在此也就抛砖引玉一下: 1.base64加密 在页面中引入base64.js文 ...

  2. Android LayoutInflater源码解析:你真的能正确使用吗?

    版权声明:本文出自汪磊的博客,未经作者允许禁止转载. 好久没写博客了,最近忙着换工作,没时间写,工作刚定下来.稍后有时间会写一下换工作经历.接下来进入本篇主题,本来没想写LayoutInflater的 ...

  3. js 的 骚操作

    单行的js 代码虽然简洁,但却不易维护,甚至难以理解, 但这却并不影响前端童鞋们编写简洁代码的热情, 一   , 生成随机ID // 生成长度为10的随机字母数字字符串 Math.random().t ...

  4. 大数据技术之_19_Spark学习_02_Spark Core 应用解析小结

    1.RDD 全称 弹性分布式数据集 Resilient Distributed Dataset它就是一个 class. abstract class RDD[T: ClassTag](    @tra ...

  5. gem安装redis库时报错

    报错一: [root@Redis-1 software]# /usr/local/ruby/bin/gem install redis-3.2.2.gem ERROR: Loading command ...

  6. 理解ASP.NET Core 依赖注入

    目录: 一.什么是依赖注入 1.1.什么是依赖? 1.2. 什么是注入? 1.3.依赖注入解决的问题 二.服务的生命周期(.Net Core DI) 三.替换默认服务容器 3.1.为什么替换默认服务容 ...

  7. [小技巧]ASP.NET Core中如何预压缩静态文件

    原文地址:Pre-compressed static files with ASP.NET Core 作者:Gunnar Peipman 译者:Lamond Lu 译文:https://www.cnb ...

  8. 3D数学 矩阵常用知识点整理

    1.矩阵了解 1)矩阵的维度和记法 (先数多少行,再数多少列) 2)矩阵的转置 行变成列,第一行变成第一列...矩阵的转置的转置就是原矩阵            即        3)矩阵和标量的乘法 ...

  9. 工厂模式讲解, 引入Spring IOC

    目录 引入 简单工厂 抽象工厂 Spring的bean工厂 模拟Spring工厂实现 模拟IOC 引入 假设有一个司机, 需要到某个城市, 于是我们给他一辆汽车 public class Demo { ...

  10. Java面试前需要了解的东西

    一.前言 只有光头才能变强 回顾前面: 广州三本找Java实习经历 上一篇写了自己面试的经历和一些在面试的时候遇到的题目(笔试题和面试题). 我在面试前针对Java基础也花了不少的时间,期间也将自己写 ...