#什么是RAC ReactiveCocoa(简称为RAC),是由Github开源的一个应用于iOS和OS开发的新框架,Cocoa是苹果整套框架的简称,因此很多苹果框架喜欢以Cocoa结尾。ReactiveCocoa5.0以后将 RAC 拆分为四个库:ReactiveCocoa、ReactiveSwift、ReactiveObjC、ReactiveObjCBridge。其中的ReactiveCocoa和ReactiveObjC,一个适用于纯Swift项目,另一个适用于纯OC项目。

#RAC的作用

  • 实现代理:rac_signalForSelector
  • 代替KVO :rac_valuesAndChangesForKeyPath
  • 监听事件:rac_signalForControlEvents
  • 实现通知:rac_addObserverForName
  • 监听文本框文字改变:rac_textSignal
  • 处理当界面有多次请求时,需要都获取到数据时,才能展示界面 rac_liftSelector:withSignalsFromArray:Signals
  • 把要处理的事件和监听的事件放在一起,使代码高聚合,低耦合

#函数式编程思想

函数式编程:就是尽可能的使用函数嵌套的方式来编程,函数式编程的目的就是尽可能的使代码高内聚,代表框架是ReactiveCocoa

##函数式编程的方法签名要求:

  • 方法的返回值是对象本身
  • 方法的参数是Block
  • Block的参数是需要操作的值
  • Block的返回值是操作的结果

#响应式编程思想: 响应式编程是一种面向数据流变化传播的编程范式。编程语言中可以很方便地表达静态或动态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播。

在响应式编程中万物皆是流。 任何事物都可以当作一个流:变量、用户输入、属性、缓存、数据结构等等。

#集成ReactiveCocoa ##纯Swift项目Cocoapods导入

podfile文件中的内容:

platform:ios, ‘8.0’
use_frameworks! 
target ‘这里写你的工程名’ do
pod 'ReactiveCocoa'              
end

##纯OC项目Cocoapods导入 podfile文件中的内容:

platform:ios, ‘8.0’
use_frameworks! 
target ‘这里写你的工程名’ do
pod 'ReactiveObjC'              
end

Tips:若项目为Swift和OC混编,那么需要将ReactiveObjC和ReactiveCocoa都导入,同时需要手动导入ReactiveObjCBridge。

#RAC的使用(代码持续更新)

#import "ViewController.h"
#import "ReactiveObjC.h"
#import "NSObject+RACKVOWrapper.h"

@interface ViewController ()

@property(strong, nonatomic) id<RACSubscriber> subscriber;

@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  
    //RACSignal:只能订阅信号,在内部由订阅者发送信号
  //创建信号
  RACSignal *signal = [RACSignal createSignal:^RACDisposable * (id<RACSubscriber> subscriber) {//订阅信号,执行subscribeNext时调用该代码块
    //发送信号
    [subscriber sendNext:@"MrFung"];
    [subscriber sendCompleted];

    return [RACDisposable disposableWithBlock:^{
      NSLog(@"信号发送完成或者错误,执行此block取消订阅,当前信号不再被订阅");
    }];
  }];

  //订阅信号
  [signal subscribeNext:^(id x){//发送数据:调用sendNext时才会调用该代码块
    NSLog(@"接收数据:%@", x);//接收数据:MrFung
  }];
  
    //RACDisposable:取消订阅
  //创建信号
  RACSignal *signal = [RACSignal createSignal:^RACDisposable * (id<RACSubscriber> subscriber) {
    //发送信号
    [subscriber sendNext:@"MrFung"];

    _subscriber = subscriber;//全局变量保存起来,系统不会取消订阅
    return [RACDisposable disposableWithBlock:^ {
      NSLog(@"取消订阅,清理资源");
    }];
  }];

  //订阅信号
  RACDisposable *dispose = [signal subscribeNext:^(id x) {
    NSLog(@"接受数据: %@", x);
  }];

  [dispose dispose];//主动取消订阅
  
  //RACSubject:既能订阅信号,也能发送信号
  //创建信号
  RACSubject *subject = [RACSubject subject];

  //订阅信号
  [subject subscribeNext:^(id x) {
    NSLog(@"接收到值: %@", x);
  }];

  //发送信号
  [subject sendNext:@"MrFung"];
  
  //RACReplaySubject:既可以先订阅信号再发送信号,也可以先发送信号再订阅信号
  //先订阅再发送:
  //创建信号
  RACReplaySubject *replaySubject = [RACReplaySubject subject];

  //订阅信号
  [replaySubject subscribeNext:^(id x) {
    NSLog(@"订阅者1接收到值: %@", x);
  }];

  //发送信号
  [replaySubject sendNext:@"MrFung"];
  
  //先发送再订阅:
  //创建信号
  RACReplaySubject *replaySubject = [RACReplaySubject subject];

  //发送信号
  [replaySubject sendNext:@"MrFung"];

  //订阅信号
  [replaySubject subscribeNext:^(id x) {
    NSLog(@"订阅者1接收到值: %@", x);
  }];
  
  //RAC的KVO:
  [self.view rac_observeKeyPath:@"alpha" options:NSKeyValueObservingOptionNew observer:nil block:^(id value, NSDictionary *change, BOOL causedByDealloc, BOOL affectedOnlyLastComponent) {
    NSLog(@"change: %@", change);
  }];

  [[self.view rac_valuesAndChangesForKeyPath:@"backgroundColor" options:NSKeyValueObservingOptionNew observer:nil] subscribeNext:^(id x) {
    NSLog(@"x:%@", x);
  }];
  
  //RAC按钮监听事件
  UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 200, 30)];
  [button setTitle:@"Button" forState:UIControlStateNormal];
  button.backgroundColor = [UIColor grayColor];

  //监听和实现在一起
  [[button rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^ (id x) {
    NSLog(@"按钮被点击了:%@", x);
  }];

  [self.view addSubview:button];
  
  //RAC通知:
  [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(id x) {
    NSLog(@"键盘即将显示");
  }];

  //RAC监听文本框内容
  [[textField rac_textSignal] subscribeNext:^ (id x) {
    NSLog(@"文本框内容改变了: %@", x);
  }];
  
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
  self.view.backgroundColor = [UIColor grayColor];
  self.view.alpha = 0.5;
}

@end

代码github地址