ReactiveCocoa

Posted petewell

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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


以上是关于ReactiveCocoa的主要内容,如果未能解决你的问题,请参考以下文章