RAC系列2之 基础篇2

注: RAC这一些列文章主要参考了小码哥袁峥雷纯峰这两位大佬的博客

ReactiveCocoa开发中常见方法

  1. rac_signalForSelector:
    1. 原理:把调用某个对象的方法转换成信号,只要调用这个方法,就会发送信号。只要提前订阅这个信号就可以监听这个对象的调用了.
    2. 作用: 监听对象的某个方法有没有调用
  2. KVO(rac_valuesForKeyPathrac_valuesAndChangesForKeyPath) :
    1. 原理: 把监听对象的属性改变转换成信号,只要只改变就发送信号
  3. rac_signalForControlEvents:
    1. 作用:用于监听某个事件
    2. 原理: 把按钮的的点击事件转换为信号,点击按钮,就回发送信号
  4. rac_addObserverForName:
    1. 作用:用于监听某个通知。
    2. OC用完观察者之后需要移除观察者,但是RAC不需要管理观察者,内部已经管理好了
  5. rac_textSignal:
    1. 作用: 监听文本框文字改变
  6. rac_liftSelector:withSignalsFromArray::
    1. 作用: 处理当一个界面有多次请求时,需要都获取到数据时,才能展示界面
    2. 当传入的Signals(信号数组),每一个signal都至少sendNext过一次,就会去触发第一个selector参数的方法。
    3. 使用注意:几个信号,参数一的方法就几个参数,每个参数对应信号发出的数据。
  7. 代码举例

     //1. rac_signalForSelector
     //自定义RedView,实现touchBegan方法
     //viewController控制器
     -(void)viewDidLoad{
     RedView *redV = [[RedView alloc] init];
     redV.backgroundColor = [UIColor redColor];
     redV.frame = CGRectMake(50, 50, 100, 100);
     [self.view addSubview:redV];
        
     [[redV rac_signalForSelector:@selector(touchesBegan:withEvent:)] subscribeNext:^(id  _Nullable x) {
         NSLog(@"点击View");
     }];
     }
        
        
     //2. KVO
     -(void)viewDidLoad{
     //KVO
     RedView *redV = [[RedView alloc] init];
     redV.backgroundColor = [UIColor redColor];
     redV.frame = CGRectMake(50, 50, 100, 100);
     [self.view addSubview:redV];
     _redV = redV;
    
     //把监听redview的frame属性改变转换成信号,只要只改变就发送信号
     //方法1:
     //程序一启动,加载RedView就会改变frame,因此开始就会调用一次
     [[redV rac_valuesForKeyPath:@"frame" observer:self] subscribeNext:^(id  _Nullable x) {
         NSLog(@"--监听属性值---");
     }];
        
     //方法2:
     //程序启动加载redView时不会调用
     [[redV rac_valuesAndChangesForKeyPath:@"frame" options:NSKeyValueObservingOptionNew observer:self] subscribeNext:^(RACTwoTuple<id,NSDictionary *> * _Nullable x) {
         NSLog(@"--监听属性变化---");
     }];
        
     }
     -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
         self.redV.frame = CGRectMake(100, 100, 200, 200);
     }
        
     //3. 监听事件
     UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 50, 50)];
     btn.backgroundColor = [UIColor redColor];
     [self.view addSubview:btn];
        
     //监听事件
     //把按钮的的点击事件转换为信号,点击按钮,就回发送信号
     [[btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
         NSLog(@"点击了按钮");
     }];
        
     //4. 监听通知
     -(void)viewDidLoad{
     UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(100, 100, 200, 30)];
     textField.backgroundColor = [UIColor redColor];
     [self.view addSubview:textField];
     //监听键盘弹出的通知
     //RAC监听
     [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) {
         NSLog(@"键盘将要弹出了");
     }];
     //OC监听
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sss:) name:UIKeyboardWillShowNotification object:nil];
     }
     -(void)sss:(id)d{
          NSLog(@"键盘将要sss弹出了");
     }
        
     //5.监听文本框的文字改变
     -(void)viewDidLoad{
     UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(100, 100, 200, 30)];
     textField.backgroundColor = [UIColor redColor];
     [self.view addSubview:textField];
     //监听TextField内容改变
     [textField.rac_textSignal subscribeNext:^(NSString * _Nullable x) {
         NSLog(@"=====%@",x);
     }];
     }
        
     //6. 同时获取到数据,刷新UI
     -(void)viewDidLoad{
     //处理当一个界面有多次请求时,需要都获取到数据时,才能展示界面
     //网络请求1
     RACSignal *signal1 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
         NSLog(@"网络请求1") ;
         [subscriber sendNext:@"网络请求1获取到的数据"];
         [subscriber sendCompleted];
         return nil;
     }];
     //网络请求2
     RACSignal *signal2 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
         NSLog(@"网络请求2") ;
         [subscriber sendNext:@"网络请求2获取到的数据"];
         [subscriber sendCompleted];
         return nil;
     }];
        
     //保证两个请求都完成的情况下才能刷新UI
     /*
      数组用于存放信号
      selector:当数组中的信号都发送数据的时候,才会调用
      selector参数个数: 与数组中的信号个数一样
      selector参数类型: 与数组中对应的信号发出的数据一一对应
      */
     [self rac_liftSelector:@selector(obtainData1: andData2:) withSignalsFromArray:@[signal1,signal2]];
     }
     //同时获取到数据,刷新UI
     -(void)obtainData1:(NSString *)data1 andData2: (NSString *)data2{
         NSLog(@"数据1===%@===数据2===%@",data1,data2);
     }
    

ReactiveCocoa常见宏

  1. RAC(TARGET, ...)
    1. 作用: 用于给某个对象的某个属性绑定。
    2. 代码举例:

       -(void)viewDidLoad{
       UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(100, 100, 200, 30)];
       textField.backgroundColor = [UIColor redColor];
       [self.view addSubview:textField];
       UILabel *label = [[UILabel alloc] init];
       label.frame = CGRectMake(100, 300, 200, 30);
       [self.view addSubview: label];
       //方法1:
       [textField.rac_textSignal subscribeNext:^(NSString * _Nullable x) {
           label.text = x;
       }];
       //方法2:
       RAC(label,text) = textField.rac_textSignal;
              
        }
      
  2. RACObserve(TARGET, KEYPATH):
    1. 作用: 监听某个对象的某个属性,返回的是信号。
    2. 代码举例:

        [RACObserve(self.view, center) subscribeNext:^(id  _Nullable x) {
       NSLog(@"属性改变%@",x);
       }];
      
  3. @weakify(Obj)@strongify(Obj):
    1. 一般两个都是配套使用
    2. 解决block的循环引用问题
    3. 代码举例:

       #import "TwoViewController.h"
       #import <ReactiveObjC/ReactiveObjC.h>
       @interface TwoViewController ()
       @property (nonatomic,strong)  RACSignal *signal ;
       @end
          
       @implementation TwoViewController
          
       - (void)viewDidLoad {
       [super viewDidLoad];
       self.view.backgroundColor = [UIColor whiteColor];
       @weakify(self);
       RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
           @strongify(self);
           NSLog(@"%@",self);
           return nil;
       }];
       self.signal = signal;
       }
      
       -(void)dealloc{
           NSLog(@"%s",__func__);
       }
       @end
      
  4. RACTuplePack
    1. 作用:把数据包装成RACTuple(元组类)
    2. 代码:

       // 把参数中的数据包装成元组
       RACTuple *tuple = RACTuplePack(@10,@20);
      
  5. RACTupleUnpack
    1. 作用: 把RACTuple(元组类)解包成对应的数据。
    2. 代码:

       // 把参数中的数据包装成元组
       RACTuple *tuple = RACTuplePack(@"xmg",@20);
              
       // 解包元组,会把元组的值,按顺序给参数里面的变量赋值
       // name = @"xmg" age = @20
       RACTupleUnpack(NSString *name,NSNumber *age) = tuple;
      
      
Table of Contents