ReactiveCocoa相关ReactiveCocoa研究ReactiveCocoa

ReactiveCocoa(FRP)-基础篇

2016-11-13  本文已影响1099人  IIronMan
  //1.使用约束框架的一个条件是 先添加控件,再进行约束

   /**
    *  创建棕色的view
    */
    UIView *view = [[UIView alloc]init];
    view.backgroundColor = [UIColor brownColor];

    [self.view addSubview:view];

     /**
      *  设置约束之前,一定要把view先添加上去(否则会崩掉)
      */

       [view mas_makeConstraints:^(MASConstraintMaker *make) {
       // 链式编程的思想特点是:方法的返回值必须是方法的调用者
       // block: 把需要的操作的值当做block参数,block也需要返回值,就是方法的调用者
    
       //设置约束
       // 给make添加left,top 约束,调用equalTo 给这两个约束赋值
    
      make.left.top.equalTo(@30);
      make.bottom.right.equalTo(@-30);
    }];

所以,你可能听说过ReactiveCocoa被描述为函数响应式编程(FRP)框架。以后使用RAC解决问题,就不需要考虑调用顺序直接考虑结果,把每一次操作都写成一系列嵌套的方法中,使代码高聚合,方便管理。

    // 1.创建信号,首先把didSubscribe保存到信号中,还不会触发。
    // 2.当信号被订阅,也就是调用signal的subscribeNext:nextBlock
    // 2.2 subscribeNext内部会创建订阅者subscriber,并且把nextBlock保存到subscriber中。
    // 2.1 subscribeNext内部会调用siganl的didSubscribe
    // 3.siganl的didSubscribe中调用[subscriber sendNext:@1];
    // 3.1 sendNext底层其实就是执行subscriber的nextBlock

    // 1.创建信号
    RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

    // block调用时刻:每当有订阅者订阅信号,就会调用block。

    // 2.发送信号
    [subscriber sendNext:@1];

    // 如果不在发送数据,最好发送信号完成,内部会自动调用[RACDisposable disposable]取消订阅信号。
    [subscriber sendCompleted];

    return [RACDisposable disposableWithBlock:^{

        // block调用时刻:当信号发送完成或者发送错误,就会自动执行这个block,取消订阅信号。

        // 执行完Block后,当前信号就不在被订阅了。

         NSLog(@"信号被销毁");

        }];
    }];

    // 3.订阅信号,才会激活信号.
    [siganl subscribeNext:^(id x) {
        // block调用时刻:每当有信号发出数据,就会调用block.
        NSLog(@"接收到数据:%@",x);
    }];
RACReplaySubject

RACReplaySubject使用步骤:

// 1.创建信号 [RACSubject subject],跟RACSiganl不一样,创建信号时没有block。
// 2.可以先订阅信号,也可以先发送信号。
// 2.1 订阅信号 - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock
// 2.2 发送信号 sendNext:(id)value

// RACReplaySubject:底层实现和RACSubject不一样。
// 1.调用sendNext发送信号,把值保存起来,然后遍历刚刚保存的所有订阅者,一个一个调用订阅者的nextBlock。
// 2.调用subscribeNext订阅信号,遍历保存的所有值,一个一个调用订阅者的nextBlock

// 如果想当一个信号被订阅,就重复播放之前所有值,需要先发送信号,在订阅信号。
// 也就是先保存值,在订阅值。

// 1.创建信号
RACReplaySubject *replaySubject = [RACReplaySubject subject];

// 2.发送信号
[replaySubject sendNext:@1];
[replaySubject sendNext:@2];

// 3.订阅信号
[replaySubject subscribeNext:^(id x) {

    NSLog(@"第一个订阅者接收到的数据%@",x);
}];

// 订阅信号
[replaySubject subscribeNext:^(id x) {

    NSLog(@"第二个订阅者接收到的数据%@",x);
}];

RACReplaySubject与RACSubject区别:RACReplaySubject可以先发送信号,在订阅信号,RACSubject就不可以。

    1. OC写法
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"flags.plist" ofType:nil];

    NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];

    NSMutableArray *items = [NSMutableArray array];

     for (NSDictionary *dict in dictArr) {
           FlagItem *item = [FlagItem flagWithDict:dict];
           [items addObject:item];
      }

    2 RAC写法
       NSString *filePath = [[NSBundle mainBundle] pathForResource:@"flags.plist" ofType:nil];

       NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];

       NSMutableArray *flags = [NSMutableArray array];

       _flags = flags;

       // rac_sequence注意点:调用subscribeNext,并不会马上执行nextBlock,而是会等一会。
       [dictArr.rac_sequence.signal subscribeNext:^(id x) {
        // 运用RAC遍历字典,x:字典

        FlagItem *item = [FlagItem flagWithDict:x];

        [flags addObject:item];

     }];

     NSLog(@"%@",  NSStringFromCGRect([UIScreen mainScreen].bounds));

     // 3.3 RAC高级写法:
     NSString *filePath = [[NSBundle mainBundle] pathForResource:@"flags.plist" ofType:nil];

     NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];
     // map:映射的意思,目的:把原始值value映射成一个新值
     // array: 把集合转换成数组
     // 底层实现:当信号被订阅,会遍历集合中的原始值,映射成新值,并且保存到新的数组里。
     NSArray *flags = [[dictArr.rac_sequence map:^id(id value) {

           return [FlagItem flagWithDict:value];

     }] array];
  - 第1种代替KVO下面的方法在  NSObject+RACKVOWrapper.h 类里面(这个类没有在`#import "ReactiveCocoa.h"`里面,需要自己导入)    
        [self.redView rac_observeKeyPath:@"frame" options:NSKeyValueObservingOptionNew observer:nil block:^(id value, NSDictionary *change, BOOL causedByDealloc, BOOL affectedOnlyLastComponent) {
     
           NSLog(@"被调用");
     
         }];

  - 第2种代替KVO,默认会先走一次,rac_valuesAndChangesForKeyPath:用于监听某个对象的属性改变。

        [[self.redView rac_valuesForKeyPath:@"name" observer:nil] subscribeNext:^(id x) {
     
             NSLog(@"改变的值为=%@",x);
        }];
RAC代替通知.png
   // 把监听到的通知转换信号
    [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(id x) {
    NSLog(@"键盘弹出");
    }];

注意:创建信号类连接有2种方式

  //方式1
  RACMulticastConnection *multicastConnection = [singal publish];
  //方式2
  RACMulticastConnection *multicastConnection = [singal multicast:[RACReplaySubject subject]];
RACCommand使用注意

方式1.拿回数据


方式1.拿回数据

方式2.拿回数据


方式2.拿回数据
方式3.拿回数据
方式3.拿回数据

代码:

    // 1.创建命令
    RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {

         NSLog(@"执行命令");

    // 创建空信号,必须返回信号
    //        return [RACSignal empty];

    // 2.创建信号,用来传递数据
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

        [subscriber sendNext:@"请求数据"];

        // 注意:数据传递完,最好调用sendCompleted,这时命令才执行完毕。
        [subscriber sendCompleted];

        return nil;
     }];

    }];

     // 强引用命令,不要被销毁,否则接收不到数据
    _conmmand = command;
 
    // 3.执行命令
    [self.conmmand execute:@1];

     // 4.订阅RACCommand中的信号
     [command.executionSignals subscribeNext:^(id x) {

       [x subscribeNext:^(id x) {

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

    }];

    // RAC高级用法
    // switchToLatest:用于signal of signals,获取signal of signals发出的最新信号,也就是可以直接拿到RACCommand中的信号
    [command.executionSignals.switchToLatest subscribeNext:^(id x) {

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

    // 5.监听命令是否执行完毕,默认会来一次,可以直接跳过,skip表示跳过第一次信号。
    [[command.executing skip:1] subscribeNext:^(id x) {

    if ([x boolValue] == YES) {
        // 正在执行
        NSLog(@"正在执行");

    }else{
        // 执行完成
        NSLog(@"执行完成");
      }
    }];

进阶篇下篇介绍


记得点个喜欢哦❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️

上一篇下一篇

猜你喜欢

热点阅读