ReactiveCocoa-一个你值得关注的东西-例子

前端之家收集整理的这篇文章主要介绍了ReactiveCocoa-一个你值得关注的东西-例子前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

一、ReactiveCocoa是什么?

ReactiveCocoa是最近在GitHub上非常火的一个框架,是基于响应式编程开发的。ReactiveCocoa

关于响应式编程,这个维基百科有解释:响应式编程

维基百科举的例子是这样:

代码中有a=b+c,一旦执行后,b或者c变化,除非再次执行一遍,a不会再变化。而响应式编程的思想,就是b或者c变化时,a的值也随之变化。就像Excel表格中,如果在C1中写入公式:=SUM(A1;B1),也就是说无论A1或者B1发生多少变化,C1值总会根据这个公式自己做变化。为什么微软这么屌,因为响应式编程就是最先从微软实验室得出来的。请参考:Reactivite Extension


二、我写这篇博客的目的

因为我用了,发现不仅从上手程度、功能性、逻辑性、易用性上都非常出色。你可以不必须掌握它,因为目前好像还没有产品是用它来开发的,而且这个ReactiveCocoa还在不断的扩展中。

三、举个例子吧

我有这么一个需求:

1、2个输入框,1个按钮

2、第一个输入框只有满足输入:"我爱刘力"后左侧图片显示对勾。

3、只有第一个满足条件了,第二个才可以输入。而且第二个必须输入的内容不和第一个相同,但最后两个字包含“刘力”,左侧的图片显示对勾。

4、只有前2个输入框都符合条件了,按钮才可以点击enable=YES

5、按钮点击后出来趣味Alert框。


如图:

图一 都不满足条件

图2 只有第一个输入框满足条件后,第二个输入框变化placeholder,并可以输入

图3 都符合条件时,按钮可以点击

图4 点击按钮弹出Alert,选择想或者不想

思考:很简单的一个例子。如果我们常规来写的话,我觉得应该是这样的顺序:

1、第一个textfield的代理方法中进行判断,如果符合条件,出现对勾,将第二个textfield替换Placeholder,并可输入。

2、同1,在第二个textfield的代理方法中进行判断,如果符合,将按钮enable置为YES,替换Title和按钮上的颜色

听起来也不是很复杂,但我们看看如果用ReactiveCocoa来写会是如何的?

这里需要指出,ReactiveCocoa引用了信号源这么一个东西,关于这个解释,我直接引用某位大神的说法:

ReactiveCocoagithub去年开源的一个项目,是在iOS平台上对FRP的实现。FRP的核心是信号,信号在ReactiveCocoa(以下简称RAC)中是通过RACSignal来表示的,信号是数据流,可以被绑定和传递。
可以把信号想象成水龙头,只不过里面不是水,而是玻璃球(value),直径跟水管的内径一样,这样就能保证玻璃球是依次排列,不会出现并排的情况(数据都是线性处理的,不会出现并发情况)。水龙头的开关默认是关的,除非有了接收方(subscriber),才会打开。这样只要有新的玻璃球进来,就会自动传送给接收方。可以在水龙头上加一个过滤嘴(filter),不符合的不让通过,也可以加一个改动装置,把球改变成符合自己的需求(map)。也可以把多个水龙头合并成一个新的水龙头(combineLatest:reduce:),这样只要其中的一个水龙头有玻璃球出来,这个新合并的水龙头就会得到这个球。

首先,我们需要引入ReactiveCocoa框架,这里我用的CocoaPods来管理的,如果你不知道CocoaPods的话,看看唐巧的博客使用CocoaPods来做iOS程序的包依赖管理

开始上代码

#import "TableViewViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>

//下面的两张图用在是否符合要求
#define Wrong [UIImage imageNamed:@"checkBox"]
#define Right [UIImage imageNamed:@"checkSelected"]


@interface TableViewViewController ()

@property(nonatomic,retain)UITextField *textFieldOne;

@property(nonatomic,retain)UITextField *textFieldTwo;

//创建2个输入框的信号源
@property(nonatomic,strong)RACSignal *textFieldOneSignal;
@property(nonatomic,strong)RACSignal *textFieldTwoSignal;

//创建一个合并的信号源
@property(nonatomic,strong)RACSignal *bothTwoTextFieldSignal;


@end

@implementation TableViewViewController

- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}

- (void)viewDidLoad
{
[super viewDidLoad];

// Uncomment the following line to preserve selection between presentations.
// self.cleaRSSelectionOnViewWillAppear = NO;

// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return 3;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
cell.selectionStyle = UITableViewCellSelectionStyleNone;

if (indexPath.row == 0) {
self.textFieldOne = [self creatTextFieldWithView:cell.contentView WithPlaceHolderStr:@"请输入:我爱刘力"];
UIImageView * imageView = [self creatImageViewWithView:self.textFieldOne];
self.textFieldOne.leftView = imageView;
//信号创建
self.textFieldOneSignal = [self.textFieldOne.rac_textSignal map:^id(NSString * value) {
//返回下面这两个判断的值
return @((value.length>=1)&&([value isEqualToString:@"我爱刘力"]));
}];
//map是改变自己的需求
RAC(imageView,image) = [self.textFieldOneSignal map:^id(NSNumber * value) {
if (value.boolValue) {
return Right;
}
return Wrong;
}];

}

if (indexPath.row == 1) {

self.textFieldTwo = [self creatTextFieldWithView:cell.contentView WithPlaceHolderStr:@"不能和上一个一样,但最后两字必须含“刘力”"];
UIImageView * imageView = [self creatImageViewWithView:self.textFieldTwo];
self.textFieldTwo.leftView = imageView;

//将输入框2的enable属性和输入框1的信号源进行等价

//将输入框2enable属性和输入框1的信号源进行等价

RAC(self.textFieldTwo,enabled) = self.textFieldOneSignal;

[self.textFieldOneSignal subscribeNext:^(NSNumber *x) {

if (![x boolValue]) {

self.textFieldTwo.enabled = NO;

self.textFieldTwo.placeholder = @"第一个不对,就没办法在我这输入,哈哈";

}else

{

self.textFieldTwo.enabled = YES;

self.textFieldTwo.placeholder = @"不能和上一个一样,但最后两字必须含刘力”";

}

}];



//信号创建
self.textFieldTwoSignal = [self.textFieldTwo.rac_textSignal map:^id(NSString * value) {
//返回下面这两个判断的值
return @((value.length>=1)&&([value hasSuffix:@"刘力"])&&(![value isEqualToString:@"我爱刘力"]));
}];
//map是改变自己的需求
RAC(imageView,image) = [self.textFieldTwoSignal map:^id(NSNumber * value) {
if (value.boolValue) {
return Right;
}
return Wrong;
}];


}



}

if (indexPath.row == 2) {

//在这个地方去指定合并信号源,因为前两个信号源已经生成
self.bothTwoTextFieldSignal = [RACSignal combineLatest:@[self.textFieldOneSignal,self.textFieldTwoSignal] reduce:^(NSNumber*textFieldOne,NSNumber*textFieldTwo){

//2个合并成一个,如果2个都符合条件,合并信号源也输出YES,否则NO
return @(textFieldOne.boolValue&&textFieldTwo.boolValue);
}];


UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setTitleColor:[UIColor grayColor] forState:UIControlStateHighlighted];
button.frame = cell.contentView.bounds;
[cell.contentView addSubview:button];

//将按钮的是否可点击与2个输入框是否符合条件进行绑定

RAC(button,enabled)=self.bothTwoTextFieldSignal;

//条件的扩展,改变颜色

[self.bothTwoTextFieldSignal subscribeNext:^(NSNumber *x) {

if (x.boolValue) {

[button setTitleColor:[UIColor greenColor] forState:UIControlStateNormal];

[button setTitle:@"恭喜你,你可以点我" forState:UIControlStateNormal];


}else

{

[button setTitleColor:[UIColor redColor] forState:UIControlStateNormal];

[button setTitle:@"哎,你不符合,不可以点我" forState:UIControlStateNormal];


}

}];


//将按钮的按下时进行绑定
[[button rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
//将按钮执行的方法放置这里面

UIAlertView * alertView = [[UIAlertView alloc]initWithTitle:@"恭喜你" message:@"看来你是真心爱刘力,想成为神仙么?" delegate:self cancelButtonTitle:@"想" otherButtonTitles:@"不想",nil];
[alertView show];
[alertView.rac_buttonClickedSignal subscribeNext:^(NSNumber *x) {
if ([x isEqualToNumber:[NSNumber numberWithInteger:0]]) {
//这里点了第0个按钮

UIAlertView * alertViewOne = [[UIAlertView alloc]initWithTitle:@"你已经成为神仙了" message:@"你回家看看你床底下,多了500万,赏给你的" delegate:self cancelButtonTitle:@"哎呀,我回家了" otherButtonTitles:nil,nil];
[alertViewOne show];

}else
{
//这里点了第一个按钮
UIAlertView * alertViewTwo = [[UIAlertView alloc]initWithTitle:@"你不想当神仙?!!" message:@"你看看你的皮夹,没钱了吧!我变没了!" delegate:self cancelButtonTitle:@"我知道错了" otherButtonTitles:nil,nil];
[alertViewTwo show];

}
}];
}];


}


// Configure the cell...

return cell;
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 100;
}

#pragma mark- 创建输入框
-(UITextField*)creatTextFieldWithView:(UIView*)view WithPlaceHolderStr:(NSString*)placeHolderStr
{
UITextField * field = [[UITextField alloc]initWithFrame:view.bounds];
field.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
field.leftviewmode=UITextFieldviewmodeAlways;
field.autocapitalizationType = UITextAutocapitalizationTypeNone;
field.autocorrectionType = UITextAutocorrectionTypeNo;
field.clearButtonMode = UITextFieldviewmodeWhileEditing;
field.placeholder = placeHolderStr;
field.font = [UIFont systemFontOfSize:12];
[view addSubview:field];

return field;

}


#pragma mark- 创建imageview
-(UIImageView*)creatImageViewWithView:(UIView*)view
{
UIImageView * imageView = [[UIImageView alloc]initWithFrame:CGRectMake(CGRectGetMinX(view.bounds),CGRectGetMinY(view.bounds),CGRectGetHeight(view.bounds),CGRectGetHeight(view.bounds))];

return imageView;

}



4、总结。

就针对这个例子来讲,我们用ReactiveCocoa会使代码简洁,可读性高。比如,textfield无需在代理里判断,button的响应方法直接用block来替代,alert的按下也无需在代理里面判断。最重要的是,信号源一旦变化,其对应的触发将同步变化。这是一个简单的Demo,后续会逐步研究比较高难度的,比如替换KVO、比如网络下载、比如替换NSOperation等等...

作为一个程序员,除了敲代码,也要密切跟踪最新技术走向,我觉得对我们是有好处的。

原文链接:https://www.f2er.com/react/308178.html

猜你在找的React相关文章