Reactivecocoa全解析 1.FRP编程思想
CommentReactiveCocoa全解析 1.FRP编程思想
ReactiveCocoa是我在开发工作中重度使用的一个开源框架,当你使用MVVM设计模式的时候,它几乎是你最好的选择,当然你也可以使用其他的一些方式来完成数据绑定,KVO,delegate或者是block,但是RAC为你提供了更优雅更安全的绑定方式,我们可以使用RAC在View和ViewModel中充当binder的角色来实现数据的同步,也可以把RAC放在ViewModel层,使用signal来异步获取数据,比如网络请求,访问数据库等。
因为RAC是一个使用起来并不那么容易的开源框架,所以接下来我会分几个部分来介绍它:
ReactiveCocoa是Gitbub开源的一个函数响应式编程框架,它是iOS上的函数响应式编程(FRP)体现,要理解RAC,首先我们就要理解函数响应式编程(FRP),刚开始接触FRP可能有一些困扰,因为它和我们以往的编程方式区别很大,接下来我们回顾一下现在常用的编程方式:面向对象编程(OOP)和面向协议编程(POP)
###面向对象编程(OOP
从我们刚开始学习编程,接触到的最多就是面向对象编程(OOP),OOP的优点很多,继承,抽象,多态,可重用性,可维护性等等,我们从很早就知道了万物皆可盘(误 ,应该是万物皆对象的编程思想,当然有人也有一些质疑,比如结构体和对象的关系等,抛开这些争论,面向对象仍然是一种灵活的,易于维护的编程方式。
###面向协议编程(POP)
面向协议编程(POP)是我在使用Swift时用到的编程方式。我在15-16年中使用Swift来完成编程工作,现在因为一些原因我又回到了Objective-C阵营,但我仍无比的怀念Swift,其中一个重要原因,就是Swift对面向协议编程的友好支持。
苹果公司声明:从核心上说,Swift是面向协议的
POP拥有OOP的大部分特点,他们之间最大的区别是:类只能继承一个类(这里只讨论iOS开发语言,像一些编程语言比如C++的确拥有多继承,但是多继承在工作中仍然不是一个很好的特性),而类可以实现多个协议。我们可以举一个例子,如果现在要创建漫威英雄的类,我们要怎么创建?
创建一个父类,拥有fly,land方法, SuperHero:fly(),land()
子类Super Man:
子类Iron Man:
子类Spider Man:
我们都知道小蜘蛛是没有飞行能力的,所以在这里将fly和land方法放在父类中并不可行,我们必须在父类删除fly和land,在超人和钢铁侠中单独加入fly和land,但是拥有飞行能力的超级英雄并不少见,我们接下来不得不为猎鹰,幻世,绯红女巫他们挨个加上。所以面向对象在这里并不是很可靠,换个思路,这里我们用POP试一下
创建一个fly协议,拥有fly和land两个方法,因为飞行和降落都是对应的,所以这里没有什么问题,接下来我们只要将拥有飞行能力的超级英雄实现fly协议,这样使用这个fly协议的超级英雄就拥有了飞行能力,当然我们也可以建立更多的协议,来为超级英雄增加更多的能力。
编程思想并没有孰优孰劣,我们这里只是做一个简单介绍,接下介绍一下今天的重点,函数响应式编程(FRP)。
###函数响应式编程(FRP)
FRP全称Function Reactive Programing,它包含了两个部分,函数式编程 Function Programing(FP)和响应式编程 Reactive Programing(RP),
####响应式编程
我们先来看一段代码,
int a = 3;
int b = 5;
int c = a + b;
a = 8;
NSLog(@“c = %d”, c); //8
这是我们熟悉的编程方式,首先为a和b进行赋值,然后将a + b的指赋给c,打印c的结果为8,接下来修改a和b的值后重新打印c,此时c的值仍然是8。因为代码中的 a + b只是一个瞬时的操作,并不是一段关系的描述。
而响应式编程是一种面向数据流和变化传播的编程范式,这意味着可以再编程语言中很方便的表达静态和动态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播,所以在响应式编程中,上述例子中的c 会跟根据a、b值得变化而发生变化
在app的登录界面中,我们常常需要通过判断用户名和密码是否填写合法后来设置登陆按钮的可点击状态,这里我们可以对userNameTextField和passwordTextField进行监听,然后将监听的结果合并后进行合法性判断,最后将处理的结果绑定到登陆按钮上,这在RAC中是一个最常用的写法,当userNameTextField和passwordTextField发生变化时,登陆按钮的状态会相应的发生变化。
1 | RAC(self.viewModel, username) = self.usernameTexField.rac_textSignal; |
另外一个典型的例子,在iOS开发中我们用Autolayout设置约束来描述视图之间的位置关系,当某一个约束发生改变后,其他的约束就会响应发生变化,这里也是响应式编程的体现。
####函数式编程
函数式编程将计算机运算视为函数运算,并且避免使用程序状态和易变对象,在函数式编程中函数可以像其他数据类型一样,处于平等的地位,可以作为参数传递到另一个函数中,可以赋值给其他的变量,也可以做为别的函数的返回值。
我们可以使用RAC提供的一系列高阶函数来实现函数式编程,比如map,falltenMap,,filter,reduce,merge,combinte等等,在接下来的文章中我会介绍一下RAC为我们提供的常用的高阶函数。
到这里大家应该已经对FRP编程思想有一些认识,接下来我会介绍以下RAC为我们提供的高阶函数,已经如何如果使用它们来解决开发工作中可能遇到的一些问题。
说了这么多,那么使用FRP到底有什么好处呢,我觉得使用FRP可以为我们解决以下几个问题:
过多的状态值
vc中的冗余代码
消息传递机制
Event之间的组合,交互
多请求的处理