由于工作原因,有段时间没更新博客了,甚是抱歉,只是,从今天開始我又活跃起来了,哈哈,于是决定每周更新一博。大家互相学习。交流。

今天呢。讨论一下关于ReactiveCocoa,这个採用函数响应式编程(FRP)的框架,下面会对ReactiveCocoa简称为RAC。

之前看过一遍文章,说的是作为一个iOS开发人员,写的每一行代码差点儿都是在对应某个事件,比如button的点击。收到网络消息,属性的变化(通过KVO)或者用户位置的变化(通过CoreLocation)。可是这些事件都用不同的方式来处理,比方action、delegate、KVO、callback等。

我非常赞同这种说法,于是。即然这种话,那我们为什么不把这些须要响应的事件流统一放在一起呢。非常幸运的是,Github有一个开源项目,即 ReactiveCocoa简称RAC,就是基于响应式编程思想的Objective-C实践。

何为RAC呢:RAC是为应用中发生的不同事件流提供了一个标准接口。我们能够使用一些基本工具来更easy的连接、过滤和组合。

RAC结合了几种编程风格:

函数式编程(Functional Programming):使用高阶函数。比如函数用其它函数作为參数。

响应式编程(Reactive Programming):关注于数据流和变化传播。

所以,你可能听说过ReactiveCocoa被描写叙述为函数响应式编程(FRP)框架。

有句比喻非常好非常形象的对RAC做了总结:

“能够把信号想象成水龙头,仅仅只是里面不是水,而是玻璃球(value),直径跟水管的内径一样,这样就能保证玻璃球是依次排列。不会出现并排的情况(数据都是线性处理的,不会出现并发情况)。水龙头的开关默认是关的。除非有了接收方(subscriber),才会打开。

这样仅仅要有新的玻璃球进来,就会自己主动传送给接收方。

能够在水龙头上加一个过滤嘴(filter)。不符合的不让通过,也能够加一个修改装置,把球改变成符合自己的需求(map)。

也能够把多个水龙头合并成一个新的水龙头(combineLatest:reduce:),这样仅仅要当中的一个水龙头有玻璃球出来,这个新合并的水龙头就会得到这个球。


--  来自博文 http://blog.csdn.net/xdrt81y/article/details/30624469



  首先导入RAC框架:

    能够通过CocoaPods导入RAC框架:

platform:ios,'9.0'

use_frameworks! #导入才不会报错

pod'ReactiveCocoa'

  RAC为应用中发生的不同事件流提供了一个标准接口。

在ReactiveCocoa术语中这个叫做信号(signal),由RACSignal类表示。

ReactiveCocoa
signal(RACSignal)发送事件流给它的subscriber(订阅者)。

眼下总共同拥有三种类型的事件:next、error、completed。一个signal在因error终止或者完毕前,能够发送随意数量的next事件。RACSignal有非常多方法能够来订阅不同的事件类型。每一个方法都须要至少一个block。当事件发生时就会运行block中的逻辑。

  ReactiveCocoa框架使用category来为非常多基本UIKit控件加入signal。这样就能给控件加入订阅了,text
field的rac_textSignal就是这么来的。

  看个样例:

RACSignal *usernameSourceSignal =self.usernameTextField.rac_textSignal;

RACSignal *filteredUsername = [usernameSourceSignalfilter:^BOOL(id
value) {

NSString *string = value;

return string.length >3; 
 }];

[filteredUsernamesubscribeNext:^(id x) {

NSLog(@"%@",x);  }];

在这里。rac_textSignal是起始事件。然后数据通过一个filter。假设这个事件包括一个长度超过3的字符串,那么该事件就能够通过。

管道的最后一步就
 是subscribeNext:,block在这里打印出事件的值。

filter操作的输出也是RACSignal。

   事实上。RACSignal的每一个操作都会返回一个RACsignal,这在术语上叫做连贯接口(fluent
interface)。这个功能能够让你直接构建管道。而不用每一步都使用本地变量。

  于是将上面的样例。能够变成:

      [[self.usernameTextField.rac_textSignalfilter:^BOOL(NSString*
string) {

return  string.length >3 ;

}]subscribeNext:^(id x) {

NSLog(@"*** %@",x);

}];

类型转换:

我们能够使用map(转换)操作通过block改变事件的数据。

map从上一个next事件接收数据。通过运行block把返回值传给下一个next事件。在上面的代码中,map以NSString为输入,取字符串的长度,返回一个NSNumber。

举个栗子:

[[[self.usernameTextField.rac_textSignalmap:^id(NSString
*text) {

return@(text.length);

}]filter:^BOOL(NSNumber *length
) {

return  [lengthintegerValue];

}]subscribeNext:^(id x) {

NSLog(@"map___%@",x);

}];

能看到map操作之后的步骤收到的都是NSNumber实例。你能够使用map操作来把接收的数据转换成想要的类型。仅仅要它是个对象。



创建有效状态信号:

     首先要做的就是创建一些信号,比方常见的登录界面,来表示username和password输入框中的输入内容是否有效,如:

RACSignal *validUsernameSignal = [self.usernameTextField.rac_textSignalmap:^id(NSString
*text) {

return@([selfisValidUsername:text]);

}];

RACSignal *validPasswordSignal = [self.passwordTextField.rac_textSignalmap:^id(id
value) {

NSString *text = value;

return@([selfisValidPassword:text]);

}];



我们能够转换这些信号,从而能为输入框设置不同的背景颜色。

基本上就是,你订阅这些信号,然后用接收到的值来更新输入框的背景颜色。

使用RAC宏

RAC宏同意直接把信号的输出应用到对象的属性上。

RAC宏有两个參数,第一个是须要设置属性值的对象,第二个是属性名。

每次信号产生一个next事件,传递过来的值都会应用到该属性上。

RAC(self.passwordTextField,backgroundColor) = [validPasswordSignalmap:^id(NSNumber
*passwordValid) {

NSLog(@"%d",[passwordValidboolValue]);

return [passwordValidboolValue]?[UIColorclearColor]:[UIColoryellowColor];

}];

RAC(self.usernameTextField,backgroundColor) = [validUsernameSignalmap:^id(NSNumber
*usernameValid) {

NSLog(@"%d",[usernameValidboolValue]);

return [usernameValidboolValue]?[UIColorclearColor]:[UIColoryellowColor];

}];

信号聚合

使用combineLatest:reduce:方法把几个信号RACSignal产生的最新的值聚合在一起,并生成一个新的信号。

每次这两个源信号的不论什么一个产生新值时。reduce
block都会运行,block的返回值会发给下一个信号。

RACSignal *signUpActiveSignal = [RACSignalcombineLatest:@[validUsernameSignal,validPasswordSignal]reduce:^id(NSNumber
*usernameValid,NSNumber *passwordValid){

return@([usernameValidboolValue]&&[passwordValidboolValue]);

}];

[signUpActiveSignalsubscribeNext:^(NSNumber *signupActive) {

self.signInButton.enabled
= [signupActiveboolValue];

}];

ReactiveCocoa处理button的事件

须要用到ReactiveCocoa为UIKit加入的还有一个方法,rac_signalForControlEvents。

信号中的信号

使用map方法,把button点击信号转换成了登录信号。

subscriber输出log,把map操作改成flattenMap,这个操作把button点击事件转换为登录信号,同一时候还从内部信号发送事件到外部信号。

doNext:是直接跟在button点击事件的后面。并且doNext: block并没有返回值。

由于它是附加操作,并不改变事件本身。

[[[[self.signInButton

rac_signalForControlEvents:UIControlEventTouchUpInside]

doNext:^(id x){

self.signInButton.enabled
=NO;

self.signInFailureText.hidden
=YES;

}]

flattenMap:^id(id x){

return[selfsignInSignal];

}]

subscribeNext:^(NSNumber*signedIn){

self.signInButton.enabled
=YES;

BOOL success =[signedInboolValue];

self.signInFailureText.hidden
= success;

if(success){

[selfperformSegueWithIdentifier:@"signInSuccess"sender:self];

}

}];



创建信号

     使用RACSignal的createSignal:方法来创建信号。

方法的參数是一个block,这个block描写叙述了这个信号。当这个信号有subscriber时。block里的代码就会运行。

block的參数是一个subscriber实例,它遵循RACSubscriber协议。协议里有一些方法来产生事件,你能够发送随意数量的next事件,或者用error\complete事件来终止。本例中,信号发送了一个next事件来表示登录是否成功。随后是一个complete事件。

这个block的返回值是一个RACDisposable对象。它同意你在一个订阅被取消时运行一些清理工作。当前的信号不须要运行清理操作,所以返回nil就能够了。

- (RACSignal *)signInSignal {

return [RACSignalcreateSignal:^RACDisposable
*(id subscriber){

[self.signInService

signInWithUsername:self.usernameTextField.text

password:self.passwordTextField.text

complete:^(BOOL success){

[subscribersendNext:@(success)];

[subscribersendCompleted];

}];

returnnil;

}];

}

总结:

ReactiveCocoa的核心就是信号,而它只是就是事件流,ReactiveCocoa的主旨是让你的代码更简洁易懂。这值得多想想。



这里将附上demo。欢迎大家阅读。

















函数响应式编程(FRP)框架--ReactiveCocoa的更多相关文章

  1. 函数响应式编程(FRP)—基础概念篇

    原文出处:http://ios.jobbole.com/86815/. 一函数响应式编程 说到函数响应式编程,就不得不提到函数式编程,他们俩有什么关系呢?今天我们就详细的解析一下他们的关系. 现在下面 ...

  2. 函数响应式编程(FRP)从入门到”放弃”——基础概念篇

    前言 研究ReactiveCocoa一段时间了,是时候总结一下学到的一些知识了. 一.函数响应式编程 说道函数响应式编程,就不得不提到函数式编程,它们俩到底有什么关系呢?今天我们就详细的解析一下他们的 ...

  3. 函数响应式编程(FRP)思想-Callback风格

    序 ReactiveCocoa是IOS广为使用的技术框架,而ReactiveCocoa的核心思想就FRP.FRP不同于JAVA的object-oriented和AOP,FRP能让你的代码像数学一样简洁 ...

  4. ReactiveCocoa,最受欢迎的iOS函数响应式编程库(2.5版),没有之一!

    简介 项目主页: ReactiveCocoa 实例下载: https://github.com/ios122/ios122 简评: 最受欢迎,最有价值的iOS响应式编程库,没有之一!iOS MVVM模 ...

  5. 函数响应式编程及ReactiveObjC学习笔记 (-)

    最近无意间看到一个视频讲的ReactiveObjC, 觉得挺好用的 但听完后只是了解个大概. 在网上找了些文章, 有的写的比较易懂但看完还是没觉得自己能比较好的使用RAC, 有的甚至让我看不下去 这两 ...

  6. RxJS入门之函数响应式编程

    一.函数式编程 1.声明式(Declarativ) 和声明式相对应的编程⽅式叫做命令式编程(ImperativeProgramming),命令式编程也是最常见的⼀种编程⽅式. //命令式编程: fun ...

  7. RxSwift 函数响应式编程

    Max 在 Boston 上学,在 San Francisco 工作,是一名软件工程师及创业者.当他还在高中的时候就在一家创业公司工作了,他非常喜欢使用 iOS.Android 以及 JavaScri ...

  8. 函数响应式编程RxJava

    RxJava 到底是什么 一个词:异步. RxJava 在 GitHub 主页上的自我介绍是 "a library for composing asynchronous and event- ...

  9. 函数响应式编程及ReactiveObjC学习笔记 (二)

    之前我们初步认识了RAC的设计思路跟实现方式, 现在我们再来看看如果使用它以及它能帮我们做什么 One of the major advantages of RAC is that it provid ...

随机推荐

  1. Tasker to auto record incoming or outgoing call

    Tasker to auto record incoming or outgoing call most of time, i was thinking of tasker can do the jo ...

  2. Android 菜单键和返回键互换

    打开RE管理器找到system/usr/keylayout/ 长按qwerty.kl选择以文本编辑器查看 将里面的MENU和BACK全部替换掉 保存,退出管理器,重启手机,菜单键和返回键的位置就调换过 ...

  3. 《TCP/IP具体解释卷2:实现》笔记--IP:网际协议

    本章介绍IP分组的结构和主要的IP处理过程,包含输入,转发和输出. 下图显示了IP层常见的组织形式. 在之前的文章中.我们看到了网络接口怎样把到达的IP分组放到IP输入队列ipintrq中去,并怎样调 ...

  4. Selenium2+python自动化52-unittest执行顺序

    前言 很多初学者在使用unittest框架时候,不清楚用例的执行顺序到底是怎样的.对测试类里面的类和方法分不清楚,不知道什么时候执行,什么时候不执行. 本篇通过最简单案例详细讲解unittest执行顺 ...

  5. java环境配置错误集锦

    eclipse生成的文件目录 D:\eeworkspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps 1.java. ...

  6. C/C++嵌入式开发面试题

    C/C++嵌入式开发面试题 预处理器(Preprocessor) 1. 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题) #define SECONDS_PER_YEA ...

  7. Git 学习(八)其他

    Git 学习(八)其他 通过以上七章Git的学习,基本操作已差不多了,本章介绍一点落网之鱼:  包括如何忽略文件.配置别名.以及使用GitHub等. 当然,Git的强大远不是七章内容可概括的,之后可结 ...

  8. 使用Jenkins和Jmeter搭建性能测试平台

    参考文档:http://blog.csdn.net/liuchunming033/article/details/52186157 jenkins的性能测试结果展现插件:https://wiki.je ...

  9. Objective-C:NSString类的常见用法

    几种常见的用法为:字符串的创建.字符串的搜索.字符串的比较.字符串的转换 用途一:字符串的创建 void ex1() { //1.常量字符串的对象 NSString *str1 = @"he ...

  10. 数学图形之罗马曲面(RomanSurface)

    罗马曲面,像是一个被捏扁的正四面体. 本文将展示罗马曲面的生成算法和切图,使用自己定义语法的脚本代码生成数学图形.相关软件参见:数学图形可视化工具,该软件免费开源.QQ交流群: 367752815 维 ...