ReactiveCocoa 初探

ReactiveCocoa 初探

一,简介

1.

ReactiveCocoa(简称为RAC),是由Github开源的一个应用于iOS和OS开发的新框架,Cocoa是苹果整套框架的简称,因此很多苹果框架喜欢以Cocoa结尾。

2.作用

在我们iOS开发过程中,经常会响应某些事件来处理某些业务逻辑,例如按钮的点击,上下拉刷新,网络请求,属性的变化(通过KVO)或者用户位置的变化(通过CoreLocation)。但是这些事件都用不同的方式来处理,比如action、delegate、KVO、callback等。其实这些事件,都可以通过RAC处理,ReactiveCocoa为事件提供了很多处理方法,而且利用RAC处理事件很方便,可以把要处理的事情,和监听的事情的代码放在一起,这样非常方便我们管理,就不需要跳到对应的方法里。非常符合我们开发中高聚合,低耦合的思想。

二,ReactiveCocoa常见类

2.1 RACSiganl:

信号类(RAC核心类),一般表示将来有数据传递,只要有数据改变,信号内部接收到数据,就会马上发出数据。
Signal会发送下面三种事件给它的接受方(subscriber)

  • next: 新的消息(value)

  • error 获取新的信号发生了错误,一般要发送一个NSError对象,表明哪里错了

  • completed 全部信号发送完毕,没有更多的信号

一个生命周期的Signal可以发送任意多个“next”事件,和一个“error”或者“completed”事件(当然“error”和“completed”只可能出现一种)

  • 创建信号
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
..............
// 创建用户登录服务器的信号
[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[self loginVithUsername:self.username
password:self.password
complete:^(bool success, NSError *error) {
if (success == true) {
[subscriber sendCompleted];
}
if (error != nil) {
[subscriber sendError:error];
}
}];
return nil;
}];
..............
// 登录接口
- (void)loginVithUsername:(NSString *)username
password:(NSString *)password
complete:(void(^)(bool success, NSError *error))completeBlock {
return [self.service loginAppWithUserName:username
andPassword:password
success:^{
completeBlock(YES,nil);
} failure:^(NSString *reason) {
NSError *error = [NSError errorWithDomain:reason code:0 userInfo:nil];
completeBlock(NO,error);
}];
}
  • 订阅信号
1
2
3
4
5
..............
//订阅textField 的文本改变信号
[_countInput.rac_textSignal subscribeNext:^(NSString *text) {
NSLog(@"%@",text);
}];
2.2 RACSubscriber

订阅者(RAC信号订阅者),表示订阅者的意思,用于发送信号,这是一个协议,不是一个类,只要遵守这个协议,并且实现方法才能成为订阅者。通过create创建的信号,都有一个订阅者,帮助他发送数据。

2.3 RACDisposable

取消订阅,用于取消订阅或者清理资源,当信号发送完成或者发送错误的时候,就会自动触发它。

  • 使用场景:不想监听某个信号时,可以通过它主动取消订阅信号。
2.4 RACCommand

RAC中用于处理事件的类,可以把事件如何处理,事件中的数据如何传递,包装到这个类中,他可以很方便的监控事件的执行过程。

  • RACCommand 使用:button 点击事件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// 创建
self.loginCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(NSString *oneTimePassword) {
@strongify(self)
OCTUser *user = [OCTUser userWithRawLogin:self.username server:OCTServer.dotComServer];
return [[OCTClient
signInAsUser:user password:self.password oneTimePassword:oneTimePassword scopes:OCTClientAuthorizationScopesUser | OCTClientAuthorizationScopesRepository note:nil noteURL:nil fingerprint:nil]
doNext:doNext];
}];
// 使用
[[self.loginButton
rac_signalForControlEvents:UIControlEventTouchUpInside]
subscribeNext:^(id x) {
@strongify(self)
[self.viewModel.loginCommand execute:nil];
}];
// 示例2
// 1.创建命令
RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
NSLog(@"执行命令")
// 创建空信号,必须返回信号
// return [RACSignal empty];
// 2.创建信号,用来传递数据
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"请求数据"];
// 注意:数据传递完,最好调用sendCompleted,这时命令才执行完毕。
[subscriber sendCompleted];
return nil;
}];
}];
// 强引用命令,不要被销毁,否则接收不到数据
_conmmand = command;
// 3.执行命令
[self.conmmand execute:@1];
// 4.订阅RACCommand中的信号
[command.executionSignals subscribeNext:^(id x) {
[x subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
}];
2.5 RACScheduler

RAC中的队列,用GCD封装的。

三,ReactiveCocoa开发中常见用法

3.1 代替代理:

rac_signalForSelector:用于替代代理。

3.2 代替KVO :

rac_valuesAndChangesForKeyPath:用于监听某个对象的属性改变。

3.3 监听事件:

rac_signalForControlEvents:用于监听某个事件。

3.4 代替通知:

rac_addObserverForName:用于监听某个通知。

3.5 监听文本框文字改变:

rac_textSignal:只要文本框发出改变就会发出这个信号。

四,ReactiveCocoa常见宏

4.1 RAC(TARGET, [KEYPATH, [NIL_VALUE]])

用于给某个对象的某个属性绑定。

// 只要文本框文字改变,就会修改label的文字
RAC(self.labelView,text) = _textField.rac_textSignal;
4.2 RACObserve(self, name)

监听某个对象的某个属性,返回的是信号。

[RACObserve(self.view, center) subscribeNext:^(id x) {

    NSLog(@"%@",x);
}];
4.3 @weakify(Obj)和@strongify(Obj)

一般两个都是配套使用,在主头文件(ReactiveCocoa.h)中并没有导入,需要自己手动导入,RACEXTScope.h才可以使用。但是每次导入都非常麻烦,只需要在主头文件自己导入就好了。

五,最佳实践

ReactiveCocoa入门教程——第一部分

ReactiveCocoa入门教程——第二部分

ReactiveCocoa开源项目:MVVMReactiveCocoa