美文网首页iOS系列(LJ)iOS相关ReactiveCocoa
深入浅出-iOS Reactive Cocoa的常见用法

深入浅出-iOS Reactive Cocoa的常见用法

作者: Yangsc_o | 来源:发表于2016-02-21 01:04 被阅读14316次


    简介

    今天的主角是Reactive Cocoa,聊聊Reactive Cocoa的常见使用:KVO、Target、Delegate、Notification。


    Reactive Cocoa 是一个重量级框架,非常的牛,为什么说Reactive Cocoa非常的牛?
    我们所熟知的iOS 开发中的事件包括:

    • Target
    • Delegate
    • KVO
    • 通知
    • 时钟
    • 网络异步回调

    ReactiveCocoa ,就是用信号接管了iOS 中的所有事件;也就意味着,用一种统一的方式来处理iOS中的所有事件,解决了各种分散的事件处理方式,显然这么一个庞大的框架学习起来也会比较难!而且如果习惯了iOS原生的编程,可能会觉得不习惯!

    先看一个图:


    ReactiveCocoa特征.png

    从这张图中,可以看出利用信号,ReactiveCocoa接管iOS 的所有事件,抛给开发者对事件作出三个相应反应;

    可以用一张图来简要说明

    next completed error.png

    RAC 的特点

    • 通过 block 函数式 + 链式 的编程,可以让所有相关的代码继承在一起!
      函数式 && 链式
    • 使用时需要注意循环引用,@weakify(self) / @strongify(self) 组合解除循环引用;

    下面用iOS开发中常见的五种事件来说明ReactiveCocoa的常见用法!

    下载框架:

    • 新建iOS工程
    • 进入终端,建立 Podfile,并且输入以下内容
    # Uncomment this line to define a global platform for your project
    platform :ios, '8.0' 
    # Uncomment this line if you're using Swift
    use_frameworks!
    pod 'ReactiveCocoa', '~> 4.0.4-alpha-4'
    
    • 版本说明:
      2.5 纯 OC
      3.0 正式版支持 Swift 1.2
      4.0 测试版支持 Swift 2.0

    在终端输入以下命令安装框架
    $ pod install

    KVO 监听

    程序实现: 监控Person name的属性变化;在touchesBegan中改变name的值,并将变化体现在UILabel上,实现KVO的监控功能;

    • 注意,RAC 的信号一旦注册不会主动释放
    • 只要在 block 中包含有 self. 一定会出现强引用* 需要使用 @weakify(self) / @strongify(self) 组合使用解除强引用
    #import <Foundation/Foundation.h>
    
    @interface Person : NSObject
    @property (nonatomic, strong) NSString *name;
    @end
    
    // ViewController.m
    #import "ViewController.h"
    @import ReactiveCocoa;
    #import "Person.h"
    
    @interface ViewController ()
    
    @property (weak, nonatomic) IBOutlet UILabel *nameLabel;
    @property (nonatomic, strong) Person *person;
    
    @end
    @implementation ViewController
    - (Person *)person 
    { 
      if (!_person) 
      { 
          _person = [[Person alloc] init]; } return _person;
      }
    - (void)viewDidLoad 
    { 
       [super viewDidLoad];
       [self demoKvo];
    }
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { 
       self.person.name = [NSString stringWithFormat:@"zhang %d",arc4random_uniform(100)];
    }
    
    /**
     * 1、为了测试此函数,增加了一个Person类 && 一个Label;点击屏幕则会等改Lable的值
     */
    #pragma -mark KVO 监听
    - (void)demoKvo {
    
        @weakify(self)
        [RACObserve(self.person, name)
            subscribeNext:^(id x) {
                 @strongify(self)
                self.nameLabel.text = x;
            }];
    }
    @end
    

    文本框输入事件监听

    #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<UITextFieldDelegate>)self.proxy;
    }
    

    通知

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

    看来看看这张图,会不会清晰很多?

    ReactiveCocoa特征.png

    这么一个强大的RAC,来试试吧?
    以上源码在gitHub:Demo链接


    参考资料1
    参考资料2
    参考资料3
    参考资料4

    相关文章

      网友评论

      • 深海蓝_98db:你好 请问Rac之通知的使用,怎么移除通知呢。
        使用情形:
        __weak typeof(self) weakSelf = self;
        [[[NSNotificationCenter defaultCenter]
        rac_addObserverForName:UIApplicationDidBecomeActiveNotification object:nil]
        subscribeNext:^(NSNotification * _Nullable x) {

        [weakSelf loadLocation];
        }];
      • Lion_Liu:demo 很nice!:+1:
      • VSCCW:学习
      • 朝雨晚风:@import ReactiveCocoa;这句话用该改成这样吧
        #import <ReactiveCocoa/ReactiveCocoa.h>
        #import <ReactiveCocoa/RACDelegateProxy.h>
        要不然在项目中会报错,使得xcode 不能正确提示
      • 虚心若愚:学习了。受益匪浅
      • 桔子听:总结的不错,没有多余的废话。
        Yangsc_o:@桔子听 谢谢😛
      • iOS程序犭袁:学习下
      • GodLoveNan:RAC一般是不是要和MVVM开发模式一起使用的?学会RAC这个大的框架,基本就不怎么用iOS原生进行编程了?
        Yangsc_o:@GodLoveNan 我添加了一个扩转阅读和参考资料,有时间可以看看。

        唐巧大神总结道:

        RAC的信号机制很容易将某一个Model变量的变化与界面关联,所以非常容易应用Model-View-ViewModel 框架。通过引入ViewModel层,然后用RAC将ViewModel与View关联,View层的变化可以直接响应ViewModel层的变化,这使得Controller变得更加简单,由于View不再与Model绑定,也增加了View的可重用性。

        RAC主要解决了三个问题:
        传统iOS开发过程中,状态以及状态之间依赖过多的问题
        传统MVC架构的问题:Controller比较复杂,可测试性差
        提供统一的消息传递机制。

        如果习惯了原生,会感到不太适应。

      本文标题:深入浅出-iOS Reactive Cocoa的常见用法

      本文链接:https://www.haomeiwen.com/subject/duivkttx.html