iOS开发之响应式编程RAC

ReactiveCocoa是什么

ReactiveCocoa(简称为RAC),响应式框架,是由Github开源的一个应用于iOS和OS开发的新框架,Cocoa是苹果整套框架的简称,因此很多苹果框架喜欢以Cocoa结尾。

在我们iOS开发过程中,经常会响应某些事件来处理某些业务逻辑,例如按钮的点击,上下拉刷新,网络请求,属性的变化(通过KVO)或者用户位置的变化(通过CoreLocation)。但是这些事件都用不同的方式来处理,比如action、delegate、KVO、callback(回调)等。

其实这些事件,都可以通过RAC处理,ReactiveCocoa为事件提供了很多处理方法,而且利用RAC处理事件很方便,可以把要处理的事情,和监听的事情的代码放在一起,这样非常方便我们管理,就不需要跳到对应的方法里。非常符合我们开发中高聚合,低耦合的思想。

这个框架能为我们带来什么样的便利

能使业务逻辑变得更加清晰

大量减少开发代码量

大量使用block块

什么时候能用到这个RAC呢

当你需要用到代理的时候开始使用它。例如用RAC检测textfiled的实时输入,不需要繁琐的遵守协议、挂代理、实现方法

涉及到点击事件的时候可以用,不需要再addtarget及实现方法。

还有通知、KVO、回调等。

具体怎么使用

创建一个新项目,使用Cocoapods在项目中导入该框架。将下面的代码复制到Podfile文件然后更新。

use_frameworks!

pod 'ReactiveCocoa', '~> 4.0.4-alpha-4'

PS:因为这个框架是采用Swift和OC混编的,所以在Podfile文件的最上面要写上use_frameworks

建pch文件,在pch文件中导入该框架。

#import "ReactiveCocoa.h"

利用这个框架实现下面需求,来具体说明他该如何使用。

两个输入框内都有内容时,下面的按钮是红色。

两个输入框内都没内容时,下面的按钮是灰色。

将下面代码粘贴到项目中的ViewController.m中。

#import "ViewController.h"

#define kMargin 100

#define kScreenWidth [UIScreen mainScreen].bounds.size.width

#define kScreenheight [UIScreen mainScreen].bounds.size.height

@interface ViewController ()

@property (nonatomic,strong) UITextField *passwordTextFiled;

@property (nonatomic,strong) UITextField *accountTextFiled;

@property (nonatomic,strong) UIButton *OKBtn;

@end

--

@implementation ViewController

- (void)viewDidLoad {

[super viewDidLoad];

//账号输入框

self.accountTextFiled = [[UITextField alloc]initWithFrame:CGRectMake(kMargin, kMargin, kScreenWidth-kMargin*2, 50)];

self.accountTextFiled.placeholder = @"账号";

self.accountTextFiled.layer.masksToBounds = YES;

self.accountTextFiled.layer.cornerRadius = 5;

self.accountTextFiled.textAlignment = NSTextAlignmentCenter;

self.accountTextFiled.backgroundColor = [UIColor grayColor];

[self.view addSubview:self.accountTextFiled];

//密码输入框

self.passwordTextFiled = [[UITextField alloc]initWithFrame:CGRectMake(kMargin, kMargin*2, kScreenWidth-kMargin*2, 50)];

self.passwordTextFiled.backgroundColor = [UIColor grayColor];

self.passwordTextFiled.placeholder = @"密码";

self.passwordTextFiled.textAlignment = NSTextAlignmentCenter;

self.passwordTextFiled.layer.masksToBounds = YES;

self.passwordTextFiled.layer.cornerRadius = 5;

[self.view addSubview:self.passwordTextFiled];

//确定按钮

self.OKBtn = [UIButton buttonWithType:UIButtonTypeCustom];

self.OKBtn.frame = CGRectMake((kScreenWidth-150)/2, kMargin*3, 150, 50);

self.OKBtn.backgroundColor = [UIColor grayColor];

[self.view addSubview:self.OKBtn];

self.OKBtn.layer.masksToBounds = YES;

self.OKBtn.layer.cornerRadius = 5;

[self.OKBtn setTitle:@"登录" forState:UIControlStateNormal];

}

@end

运行显示如下图:

效果图

不适用RAC来实现上面的需求(不写具体代码了,只写一些过程)

1、遵守协议

2、挂代理

3、实现相应的代理方法

4、在方法内写业务逻辑

使用RAC来实现该业务逻辑

1.将上面方法写入ViewController.m中。上面的RAC()其实就是一个宏定义

2.之前咱们说过RAC能帮助我们大量的减少代码而且逻辑更加清晰,在这里我们不需要在.m中找遵守协议的地方,不需要找控件挂代理,不需要去实现方法。

RAC的深入学习

1、 使用RAC给按钮添加事件

//老办法,还要实现clickBtn方法

[self.OKBtn addTarget:self action:@selector(clickBtn) forControlEvents:UIControlEventTouchUpInside];

//rac方法

[[self.OKBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {

NSLog(@"OK按钮被点击");

}];

通过rac_signalForControlEvents给按钮创建一个信号流,然后给这个信号指定一个subscribeNext(订阅者)。如果这个信号流的状态发生改变,订阅者便会受到他的改变。不仅仅button可以,segmentcontrol也同样可以。这样操作。

订阅者受到信息以后的操作都在block中操作。block返回来的参数(id x)其实就是用户所点击的按钮。程序员可以直接将(id x)改为(UIButton *sender)。

在找subcribeNext时,会看到这么一个方法

subscribeNext:nil error:nil completed:nil];

第一个参数咱已经说过了,另外事件处理有问题会回调这个error这个block块,点击事件执行完毕以后会调用completed这个block块。

2、使用RAC监听TextFiled的输入变化

[self.accountTextFiled.rac_textSignal subscribeNext:^(id x) {

NSLog(@"%@",x);

}];

self.accountTextFiled.rac_textSignal获得到textfiled的信号流。然后给这个信号指定一个(subscribeNext)订阅者。

subscribeNext:^(id x)如果输入框发生变化,订阅者会收到信息,subscribeNext后的参数,便是输入框的内容。

3、RAC的过滤效果

[[self.passwordTextfiled.rac_textSignal filter:^BOOL(id value) {

NSString *text = value;

BOOL k = [text isEqualToString:@"123"];

return k;

}] subscribeNext:^(id x) {

NSLog(@"======");

}];

这段代码最终实现的效果是,只有密码输入框输入的值是123的时候,subscribe中的代码才能执行。

之前我们已经接触过.rac_textSignal(信号流)和subscirbeNext(订阅者)。上面他们之间的filter的block块便是一个过滤器。在subscriber(订阅者)接受到文本信号变化之前,filter(过滤器)会首先拦截到这个信号。在这个filter进行一个判断,如果filter内返回一个yes,subscribe才会收到文本变化的信号流,返回NO,订阅者就不会收到信息。就好比一个母亲在给自己待嫁的女儿找婆家,只有这名母亲相中了,她才会让女儿去相亲。

4、改变订阅者收到的信息。

[[self.passwordTextFiled.rac_textSignal map:^id(NSString  *str) {

return[str boolValue] ? [UIColor clearColor]:[UIColor yellowColor];

}] subscribeNext:^(UIColor *x) {

self.view.backgroundColor = x;

}];

实现的功能:输入框有变化时改变self.view的背景颜色

之前我们subscribe收到的都是输入框的文本内容,现在我们要做的就是改变订阅者收到的信息。

在3中我们提到一个filter(过滤器),在这里我们要用一个map(映射)来改变订阅者收到的信息。之前咱们说filter的时候,在订阅者收到信息之前filter会进行一个拦截。map(映射)其实也拦截一下,拦截的时候同样会收到文本框的变化。他两唯一的不同是在map(映射)中返回的是订阅者收到的东西。上面的母亲给女儿找到了一个对象,已经结婚了。老公的第一个月工资发了,老婆(map)拿着。她那里给老公(subscribe)给你买什么东西,老公用什么东西。

5、对4优化

//对上面的优化

RAC(self.view, backgroundColor) = [self.passwordTextFiled.rac_textSignal map:^id(NSString *passwordValid){

return[passwordValid boolValue] ? [UIColor clearColor]:[UIColor yellowColor];

}];

刚开始咱们使用RAC实现咱们刚开始说的需求时,大家已经见到了RAC()。现在我们做的就是讲map(映射)中返回的颜色。赋值给RAC()中对象控件的对应属性。

总结

起初咱们说到RAC框架有以下几个特点:

1、能够使业务逻辑更清晰

2、减少代码量

3、大量使用block

最后必须要记住的一点是它能做到这一步最为重要的一个原因是

将代理、KVO、通知、callBack等一系列事件,做了一个统一管理。



 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值