iOS开发iOS技术资料

初识ReactiveCocoa

2017-07-06  本文已影响58人  绍清_shao

今天主要分享内容:

ReactiveCocoa

响应式函数编程概述

ReactiveCocoa框架让你可以在iOS应用中使用响应式函数编程(FRP)

int func(int x) 
{
  int result = 1;
  for (int i = 1; i <=x; ++i) 
  {
    result *= i;
  }
} ```
命令式编程关心解决问题的步骤
你得把达到目的的步骤详细的描述出来,
然后交给机器去运行。
需要管理非常多的中间状态量,代码繁杂。

int func(int x)
{
if (x == 1) return 1;
return x * func(x - 1);
} ```
函数式编程关心数据的映射
这里的映射就是数学上「函数」的概念,
一种东西和另一种东西之间的对应关系。
没有状态量,简洁高效。

void test() {
 int a = 5;
 int b = 6;
 int c = a + b;
 int d = funAdd(&a , &b);//a b中的值
 a = 10;
 NSLog(@"%d",c);
} ```
响应式编程是一种面向数据流和变化传播的编程范式。
在响应式编程中d的值会随着a或b的更新而更新。


### RACSignal 信号

ReactiveCocoa四大核心组件构成:
信号源:RACStream 及其子类;
订阅者:RACSubscriber 的实现类及其子类;
调度器:RACScheduler 及其子类;
清洁工:RACDisposable 及其子类。

其中,信号源又是最核心的部分,其他组件都是围绕它运作的。
ReactiveCocoa使用信号来代表异步事件,提供了一种统一的方式来处理所有异步的行为,包括代理方法、block 回调、target-action 机制、通知、KVO 等:

// 代理方法
[[self
rac_signalForSelector:@selector(webViewDidStartLoad:)
fromProtocol:@protocol(UIWebViewDelegate)]
subscribeNext:^(id x) {
// 实现 webViewDidStartLoad: 代理方法
}];

// target-action
[[self.avatarButton
rac_signalForControlEvents:UIControlEventTouchUpInside]
subscribeNext:^(UIButton *avatarButton) {
// avatarButton 被点击了
}];

// 通知
[[[NSNotificationCenter defaultCenter]
rac_addObserverForName:kReachabilityChangedNotification object:nil]
subscribeNext:^(NSNotification *notification) {
// 收到 kReachabilityChangedNotification 通知
}];

// KVO
[RACObserve(self, username) subscribeNext:^(NSString *username) {
// 用户名发生了变化
}];

### RACSignald订阅过程
// 创建信号 并发送信号
//使用RACSignal的createSignal:方法创建信号。描述这个信号的block是这个方法唯一的入参。当这个信号有订阅者的时候,block中的代码就会执行。

RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
    [subscriber sendNext:@1];
    [subscriber sendNext:@2];
    [subscriber sendCompleted];
    return [RACDisposable disposableWithBlock:^{
        NSLog(@"dispose");
    }];
}];
// 订阅信号
RACDisposable *disposable = [signal subscribeNext:^(id x) {
    NSLog(@"next value is %@",x); 
} error:^(NSError *error) {
    NSLog(@"error -> %@",[error description]);
} completed:^{
    NSLog(@"It finished success");
}];
[disposable dispose];

//ReactiveCocoa的信号(表现为RACSignal类)会向他的订阅者们发送事件流。
//发送的事件分为三种类型:next,error 和 completed。
//一个信号在因为报错或完成的终止前可以发送若干个事件。


### First Demo
实现一个登陆界面

![](https://img.haomeiwen.com/i1292402/4ff2c2884df27598.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

要求:
1. User & Password不少于3位
2. 低于3位显示红色,正常显示蓝色
3. 登录按钮只有在用户名和密码都有效输入时才能使用

Answer 1

//ReactiveCocoa框架使用category为很多标准的UIKit控件添加了信号
//可以对它们的各种事件进行订阅

//1.创建信号
RACSignal *userName = [self.usernameTextField rac_textSignal];
//2.筛选
RACSignal *validUsername = [userName filter:^BOOL(id value) {
NSString *text = value;
return [self isValidUsername:text];
}];
//3.调用信号RACSignal的subscribeNext就能订阅,
//subscribeNext:方法就提供了一个block,
//在每个next事件到达时执行里面的代码。
[validUsername subscribeNext:^(id x) {
NSLog(@"%@",x);
}];

Answer 2

[[self.usernameTextField.rac_textSignal
map:^id(NSString *username) {
return [self isValidUsername:username] ? [UIColor whiteColor] : [UIColor redColor];
}]
subscribeNext:^(UIColor *color) {
self.usernameTextField.backgroundColor = color;
}];

[[self.passworkTextField.rac_textSignal
map:^id(NSString *password) {
return [self isValidUsername:password] ? [UIColor whiteColor] : [UIColor redColor];
}]
subscribeNext:^(UIColor *color) {
self.passworkTextField.backgroundColor = color;
}];```
Answer 3

//创建两个发送布尔值的信号validUsernameSignal、validPasswordSignal
  //对用户名和密码的输入进行验证。
  RACSignal *validUsernameSignal =
  [self.usernameTextField.rac_textSignal
   map:^id(NSString *text) {
     return @([self isValidUsername:text]);
   }];
  
  RACSignal *validPasswordSignal =
  [self.passworkTextField.rac_textSignal
   map:^id(NSString *text) {
     return @([self isValidPassword:text]);
   }];
  //信号合成
  //接下来的任务就是合成这两个信号,用以共同决定登录按钮是否可用
  RACSignal *signUpActiveSignal =
  [RACSignal combineLatest:@[validUsernameSignal, validPasswordSignal]
                    reduce:^id(NSNumber *usernameValid, NSNumber *passwordValid) {
                      return @([usernameValid boolValue] && [passwordValid boolValue]);
                    }];
  //上面的代码使用combineLatest:reduce:方法   (RACSignal合成方法可以合成任意数量的信号)
  //获取validUsernameSignal和validPasswordSignal的最近一个信号值并组合成一个全新的信号。
  //每当两个源信号的其中一个发送新值,
  //reduce里的block代码块就会执行(reduce中 block的入参和源信号一一对应)
  //其返回的值会作为合成信号的值发送出去。
  
  //最后是订阅
  [signUpActiveSignal subscribeNext:^(NSNumber *signupActive) {
    self.signinBnt.enabled = [signupActive boolValue];
  }];

Second Demo

1.主动获取数据并刷新TableView
2.根据搜索关键字获取指定数据,并刷新TableView;

Demo地址

参考链接

Reactive github
美团的几篇博客
RACSignal的Subscription深入分析
raywenderlich 上的文章:
http://www.raywenderlich.com/62699/reactivecocoa-tutorial-pt1http://www.raywenderlich.com/62796/reactivecocoa-tutorial-pt2http://www.raywenderlich.com/74106/mvvm-tutorial-with-reactivecocoa-part-1http://www.raywenderlich.com/74131/mvvm-tutorial-with-reactivecocoa-part-2

上一篇 下一篇

猜你喜欢

热点阅读