ReactiveCocoa
作者:互联网
#介绍
ReactiveCocoa(其简称为 RAC)是由 Github 开源的一个应用于 iOS 和 OS X 开发的新框架。RAC 具有函数式编程和响应式编程的特性。它主要吸取了 .Net 的 Reactive Extensions 的设计和实现
#原理
这个是我看过的比较好的例子:
可以把信号想象成水龙头,只不过里面不是水,而是玻璃球(value),直径跟水管的内径一样,这样就能保证玻璃球是依次排列,不会出现并排的情况(数据都是线性处理的,不会出现并发情况)。水龙头的开关默认是关的,除非有了接收方(subscriber),才会打开。这样只要有新的玻璃球进来,就会自动传送给接收方。可以在水龙头上加一个过滤嘴(filter),不符合的不让通过,也可以加一个改动装置,把球改变成符合自己的需求(map)。也可以把多个水龙头合并成一个新的水龙头(combineLatest:reduce:),这样只要其中的一个水龙头有玻璃球出来,这个新合并的水龙头就会得到这个球
#包含的类和方法
1.类
RACSignal和RACStream
RACSubscriber:是一个协议,包含了向订阅者发送事件的方法
RACDisposable:手动移除订阅者
RACCommand:通常用来表示某个Action的执行,比如点击Button
RACScheduler:管理线程的类
常用宏定义
RAC() 可以将Signal发出事件的值赋值给某个对象的某个属性,其参数为对象名和属性名
RACObserve() 参数为对象名和属性名,新建一个Signal并对对象的属性的值进行观察,当值变化时Signal会发出事件
2.方法:
filter: 对RACStream中的事件内容进行过滤
map: 会将事件中的数据转换成你想要的数据
flattenMap: 会将内部Signal的事件传递给外部Signal
distinctUntilChanged:简单理解为“流”的值有变化时反馈变化的值
doNext: 这个向Signal管道上添加添加副作用。它并不会改变事件,参数block也没有返回值,它返回一个执行了block的Signal,这样block中的副作用就被注入到了以前的Signal。
then: 当一个订阅者被发送了completed事件后,then:方法才会执行,订阅者会订阅then:方法返回的Signal,这个Signal是在block中返回的。
deliverOn: 参数为RACScheduler类的对象scheduler,这个方法会返回一个Signal,它的所有事件都会传递给scheduler参数所表示的线程,而以前管道上的副作用还会在以前的线程上。这个方法主要是切换线程。
subscribeOn: 功能跟deliverOn:相同,但是它也会将副作用也切换到制定线程中。
#解决的问题
1.传统 iOS 开发过程中,状态以及状态之间依赖过多的问题
2.传统 MVC 架构的问题:Controller 比较复杂,可测试性差
3.提供统一的消息传递机制
#问题的具体解决方法
#状态依赖过多
例如,在用户帐户的登录界面,通常会有 2 个输入框(分别输入帐号和密码)和一个登录按钮。如果我们要加入一个限制条件:当用户输入完帐号和密码,并且登录的网络请求还未发出时,确定按钮才可以点击。通常情况下,我们需要监听这两个输入框的状态变化以及登录的网络请求状态,然后修改另一个控件的enabled状态。
```python
RAC(self.loginButton, enabled) = [RACSignal
combineLatest:@[
self.userName.rac_textSignal,
self.passWord.rac_textSignal
] reduce:^(NSString *username, NSString *password) {
return @(username.length > 0 && password.length > 0);
}];
pass
#试图解决 MVC 框架的问题
RAC 的信号机制很容易将某一个 Model 变量的变化与界面关联,所以非常容易应用 Model-View-ViewModel 框架。通过引入 ViewModel 层,然后用 RAC 将 ViewModel 与 View 关联,View 层的变化可以直接响应 ViewModel 层的变化,这使得 Controller 变得更加简单,由于 View 不再与 Model 绑定
#统一消息传递机制
iOS 开发中有着各种消息传递机制,包括 KVO、Notification、delegation、block 以及 target-action 方式,RAC 将传统的 UI 控件事件进行了封装,使得以上各种消息传递机制都可以用 RAC 来完成
```python
[[[NSNotificationCenter defaultCenter]
rac_addObserverForName:UIKeyboardDidChangeFrameNotification
object:nil]
subscribeNext:^(id x) {
NSLog(@" 键盘 Frame 改变 ");
}];
// Delegate
[[self rac_signalForSelector:@selector(viewWillAppear:)] subscribeNext:^(id x) {
NSLog(@"viewWillAppear 方法被调用 %@", x);
}];
[[[self.loginButton rac_signalForControlEvents:UIControlEventTouchUpInside] flattenMap:^RACStream *(id value) {
return [self urlResults];
}] subscribeNext:^(id x) {
NSLog(@"Sign in result: %@", x);
}];
pass
其中的[self urlResults]是自定义的方法
```python
-(RACSignal *)urlResults {
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[self signInWithUsername:self.userName.text
password:self.passWord.text
complete:^(BOOL success) {
[subscriber sendNext:@(success)];
[subscriber sendCompleted];
}];
return nil;
}];}
pass
浅入得学习了ReactiveCocoa框架,发现其实这个其实挺复杂,还需要仔细的去学习和不断地探讨.可以在平时去用它来完成以下小程序.
原文:大专栏 ReactiveCocoa
标签:RAC,Signal,线程,水龙头,ReactiveCocoa,self,block 来源: https://www.cnblogs.com/petewell/p/11614943.html