RAC

作者: 夜雨聲煩_ | 来源:发表于2018-06-01 11:03 被阅读0次

    RP

    概念

    RP(Reactive Programming)——响应编程,实际上是异步事件流(Asynchronous event stream)。

    根本

    Stream

    stream 流。一切都可以看成流,变量、用户输入、属性、事件、cache、数据结构。那么我们基于流,可以进行各种操作,combine,creat,filter,等等。对于流处理得到的数据又可以看做是新的流,以此进行不停的操作。

    而对于一个流,包括三部分,即三个 events:value,error,complete。
    当我们异步去捕获这些事件时,即为异步事件流。

    如何捕获?我们采用监听的方式,去监听 stream,也成为订阅。定义的角色就是观察者,被监听的 stream 则是被观察者,其实也就是所谓的观察者模式

    对 stream 操作

    首先对于常见的 RP 库,对于 stream 都有很多方法,mapfilterscan等等,当时他们有一个共同的特点,就是返回值是一个新的 stream。

    注意:
    上文说的是产生新的stream,也就是说对初始的那个 stream 并没有做出修改,这个特性,就是不可变性(immutability)

    新的 stream 可以继续进行相同的函数操作,这就是所谓的函数式编程

    一个小例子

    我们想在一连串的点击中检测例如鼠标点击那样的双击(包括三连击或者更高),间隔为250ms。

    我首先想到的是获取点击时间点放入数组,遍历数组获取时间间隔放入数组,再遍历获取超过250ms的时间点的 index。再对应初始数组的位置取连击位置。略显复杂,且用到多个数组和遍历操作。
    如果用流的方式的话...

    用流的方式解决问题.png
    使用throttle来设定有效时间,使用map来进行映射,使用filter进行筛选,最后生成的 stream 即是我们需要的新的 stream。我们可以通过订阅(监听)的方式来做出响应。

    优美的逻辑和代码方式。

    FRP

    概念

    函数响应式编程(英文Functional Reactive Programming),简称FRP。

    特点
    int a = 3;
    int b = 4;
    int c = a + b;
    NSLog(@"c is %d", c); // c is 7
    a = 5;
    b = 7;
    NSLog(@"c is %d", c); // 仍然是  c is 7
    

    上面就是典型的命令式编程,通过表达式和语句来改变状态量,命令式编程int c = a + b;只是一个瞬间的过程,而并不是关系描述。在传统开发中,使c的值随a、b变化而变化是比较难的。

    而响应式编程的出现就是为了描述这种实时变化的情况,也是响应式编程的核心思想。

    // 代替target-action
        [[self.confirmButton rac_signalForControlEvents:UIControlEventTouchUpInside]
         subscribeNext:^(id x) {
            // 回调内容写在这里
         }];
        
    // 代替delegate
        [[self.scrollView rac_signalForSelector:@selector(scrollViewDidScroll:) fromProtocol:@protocol(UIScrollViewDelegate)]
         subscribeNext:^(id x) {
            // 回调内容写在这里
         }];
        
    // 代替block
        [[self asyncProcess]
         subscribeNext:^(id x) {
            // 回调内容写在这里
         } error:^(NSError *error) {
            // 错误处理写到这里
         }];
        
    // 代替notification center
        [[[NSNotificationCenter defaultCenter] rac_valuesForKeyPath:@"Some-key" observer:nil]
         subscribeNext:^(id x) {
            // 回调内容写在这里
         }];
    
    // 代替KVO
        [RACObserve(self, userReportString)
         subscribeNext:^(id x) {
            // 回调内容写在这里
         }];
    

    导入

    OC版本:pod 'ReactiveObjC'
    Swift版本:pod ‘ReactiveCocoa’

    需要在podfile加上use_frameworks,重新pod install 才能导入成功

    RAC接口

    RACSignal

    介绍:

    信号,RP 中流概念(stream)在 RAC 中的对应,是贯穿 RAC 的核心概念,继承自 RACStream。

    构造方法:

    • 创建一个普通信号
    + (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe;
    
    /// 冷信号
    RACSignal *signal = [RACSignal createSignal:^ RACDisposable * (id<RACSubscriber> subscriber) { 
        [subscriber sendNext:@"foobar"]; 
        [subscriber sendCompleted]; 
        return nil; 
    }];
    
    • 创建一个立即完成的信号
    // Returns a signal that immediately completes.
    + (RACSignal<ValueType> *)empty RAC_WARN_UNUSED_RESULT;
    

    普通方法:

    • 订阅
    //订阅后的冷信号变为热信号,改变时触发block中内容
    [signal subscribeCompleted:^{ 
        NSLog(@"subscription %u", subscriptions); 
    }]; 
    
    • bool值无变化过滤
    - (RACSignal<ValueType> *)distinctUntilChanged RAC_WARN_UNUSED_RESULT;
    
    //区别于searchText每次变化同时validSearchSignal被赋值
    //加入distinctUntilChanged标记只有block内条件变化时validSearchSignal才被赋值。
      RACSignal *validSearchSignal =
        [[RACObserve(self, searchText)
          map:^id(NSString *text) {
              return @(text.length > 3);
          }]
         distinctUntilChanged];
    
    • 延迟
    - (RACSignal<ValueType> *)delay:(NSTimeInterval)interval RAC_WARN_UNUSED_RESULT;
    
    • 打印
    /// Logs all events that the receiver sends.
    - (RACSignal<ValueType> *)logAll RAC_WARN_UNUSED_RESULT;
    
    RACCommand

    介绍:

    A command is a signal triggered in response to some action, typically UI-related.
    UI Action 类型的一种信号

    构造方法:

    - (instancetype)initWithSignalBlock:(RACSignal<ValueType> * (^)(InputType _Nullable input))signalBlock;
    
    - (instancetype)initWithEnabled:(nullable RACSignal<NSNumber *> *)enabledSignal signalBlock:(RACSignal<ValueType> * (^)(InputType _Nullable input))signalBlock;
    

    enabled 决定该事件是否可用。
    block 决定点击事件处理,block 中 Input 为点击事件传参,类似于 sender,返回的 RACSignal 为事件处理结果信号。

    属性

    • executing

    A signal of whether this command is currently executing.

     //按钮点下搜索同时改变app状态栏中网络activity indicator
     RAC([UIApplication sharedApplication], networkActivityIndicatorVisible) = self.viewModel.executeSearch.executing;
    

    相关文章

      网友评论

          本文标题:RAC

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