Reactive Cocoa - 消息机制

前言

我用Reactive Cocoa有一年之久,主要使用方面:

  • 用来替代Action、delegate、notification、kvo等消息机制。

  • 封装网络请求,将传统网络请求通过Reactive Cocoa封装。

  • 用Reactive Cocoa 完美结合 MVVM框架,彻底解放控制器。

Reactive Cocoa 概念

Reactive Cocoa(也叫做RAC,下文统称RAC)是一个支持FRP(函数响应式编程)的框架。

RectiveCocoa结构

KVO监听

#pragma -mark KVO 监听
- (void)demoKvo {

    @weakify(self)
    [RACObserve(self.person, name)
        subscribeNext:^(id x) {
             @strongify(self)
            self.nameLabel.text = x;
        }];
}

文本输入监听

#pragma -mark 文本框输入事件监听
/**
 * 2、为了测试此函数,增加了一个nameText;监听文本框的输入内容,并设置为self.person.name
 */
- (void)demoTextField {

    @weakify(self);
    [[self.nameText rac_textSignal]
     subscribeNext:^(id x) {
         @strongify(self);
         NSLog(@"%@",x);
         self.person.name = x;
     }];
}

组合信号使用

#pragma -mark 文本信号组合
/**
 * 3、为了验证此函数,增加了一个passwordText和一个Button,监测nameText和passwordText
 * 根据状态是否enabled
 */
- (void)textFileCombination {

    id signals = @[[self.nameText rac_textSignal],[self.passWordText rac_textSignal]];

    @weakify(self);
    [[RACSignal
      combineLatest:signals]
      subscribeNext:^(RACTuple *x) {

          @strongify(self);
          NSString *name = [x first];
          NSString *password = [x second];

          if (name.length > 0 && password.length > 0) {

              self.loginButton.enabled = YES;
              self.person.name = name;
              self.person.password = password;

          } else  {
              self.loginButton.enabled = NO;

          }
      }];

}

按钮监听

#pragma -mark 按钮监听
/**
 * 4、验证此函数:当loginButton可以点击时,点击button输出person的属性,实现监控的效果
 */
- (void)buttonDemo {
    @weakify(self);
    [[self.loginButton rac_signalForControlEvents:UIControlEventTouchUpInside]
       subscribeNext:^(id x) {
           @strongify(self);
           NSLog(@"person.name:  %@    person.password:  %@",self.person.name,self.person.password);
       }
     ];
}

代理方法

#pragma -mark 代理方法
/**
 * 5、验证此函:nameText的输入字符时,输入回撤或者点击键盘的回车键使passWordText变为第一响应者(即输入光标移动到passWordText处)
 */
- (void)delegateDemo {

    @weakify(self)
    // 1. 定义代理
    self.proxy = [[RACDelegateProxy alloc] initWithProtocol:@protocol(UITextFieldDelegate)];
    // 2. 代理去注册文本框的监听方法
    [[self.proxy rac_signalForSelector:@selector(textFieldShouldReturn:)]
     subscribeNext:^(id x) {
         @strongify(self)
         if (self.nameText.hasText) {
             [self.passWordText becomeFirstResponder];
         }
     }];
    self.nameText.delegate = (id)self.proxy;
}

jj

 //这里订阅收到的是一个x,当一个页面存在多个tableview时,我们可以对x进行判断看是哪个tableview
  [[self rac_signalForSelector:@selector(tableView:didSelectRowAtIndexPath:) fromProtocol:@protocol(UITableViewDelegate) ] subscribeNext:^(RACTuple * x) {

      NSLog(@"点击了");

      NSLog(@"%@,%@",x.first,x.second);

  }];

  //这样子不带协议是无法代替代理的,虽然能达到效果,这个方法表示某个selector被调用时执行一段代码.带有协议参数的表示该selector实现了某个协议,所以可以用它来实现Delegate。
  //    [[self rac_signalForSelector:@selector(tableView:didSelectRowAtIndexPath:)] subscribeNext:^(RACTuple* x) {

  //        NSLog(@"%@",[x class]);

  //        NSLog(@"%@",x);
  //    }];

  //这里是个坑,必须将代理最后设置,否则信号是无法订阅到的
  //雷纯峰大大是这样子解释的:在设置代理的时候,系统会缓存这个代理对象实现了哪些代码方法
  //如果将代理放在订阅信号前设置,那么当控制器成为代理时是无法缓存这个代理对象实现了哪些代码方法的
  tableview.delegate = self;

通知

#pragma -mark 通知
/**
 * 验证此函数:点击textFile时,系统键盘会发送通知,打印出通知的内容
 */
- (void)notificationDemo {
    [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillChangeFrameNotification object:nil]
        subscribeNext:^(id x) {
            NSLog(@"notificationDemo : %@", x);
        }
     ];
}

参考文章

ReactiveCocoa讨论会
美团RAC

你可能感兴趣的:(Reactive Cocoa - 消息机制)