zoukankan      html  css  js  c++  java
  • IOS响应式编程框架ReactiveCocoa(RAC)使用示例

       ReactiveCocoa是响应式编程(FRP)在iOS中的一个实现框架,它的开源地址为:https://github.com/ReactiveCocoa/ReactiveCocoa# ;在网上看了几篇文章,感觉理论讲了很多,但是代码还是看不太懂,于是自己把它github文档上的一些使用的经典示例实现了一下,项目中有需要时可以直接搬过去用,用的熟练了再读源码也比较容易理解。

        例1. 监听对象的成员变量变化,当成员变量值被改变时,触发做一些事情。

        这种情况其实就是IOS KVO机制使用的场景,使用KVO实现,通常有三个步骤:1,给对象的成员变量添加监听;2,实现监听回调;3,取消监听;而通过RAC可以直接实现,RAC的回调是通过block实现的,类似于过程式编程,上下文也更容易理解一些。

        场景:当前类有一个成员变量 NSString *input,当它的值被改变时,发送一个请求。

        实现: 

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. [RACObserve(self, input)  
    2.     subscribeNext:^(NSString* x){  
    3.         request(x);//发送一个请求  
    4.    }];  

    每次input值被修改时,就会调用此block,并且把修改后的值做为参数传进来。

    场景:在上面场景中,当用户输入的值以2开头时,才发请求.

    实现:

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. [[RACObserve(self, input)  
    2.      filter:^(NSString* value){  
    3.          if ([value hasPrefix:@"2"]) {  
    4.              return YES;  
    5.          } else {  
    6.              return NO;  
    7.          }  
    8.      }]  
    9.      subscribeNext:^(NSString* x){  
    10.         request(x);//发送一个请求  
    11.     }];  


    场景:上面场景是监听自己的成员变量,如果想监听UITextField输入值变化,框架也做了封装可以代替系统回调

    实现:

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. [[self.priceInput.rac_textSignal  
    2.      filter:^(NSString *str) {  
    3.          if (str.integerValue > 20) {  
    4.              return YES;  
    5.          } else {  
    6.              return NO;  
    7.          }  
    8.      }]  
    9.      subscribeNext:^(NSString *str) {  
    10. <span style="white-space:pre">    </span>request(x);//发送一个请求  

    }];

    
    

    例2. 同时监听多个变量变化,当这些变量满足一定条件时,使button为可点击状态

    场景:button监听 两个输入框有值和一个成员变量值,当输入框有输入且成员变量为真时,button为可点击状态

    实现:

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. RAC(self.payButton,enabled) = [RACSignal  
    2.                                    combineLatest:@[self.priceInput.rac_textSignal,  
    3.                                                 self.nameInput.rac_textSignal,  
    4.                                                 RACObserve(self, isConnected)  
    5.                                                 ]  
    6.                                    reduce:^(NSString *price, NSString *name, NSNumber *connect){  
    7.                                    return @(price.length > 0 && name.length > 0 && [connect boolValue]);  
    8.                                    }];  

    场景:满足上面条件时,直接发送请求

    实现:

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. [[RACSignal  
    2.                                    combineLatest:@[self.priceInput.rac_textSignal,  
    3.                                                 self.nameInput.rac_textSignal,  
    4.                                                 RACObserve(self, isConnected)  
    5.                                                 ]  
    6.                                    reduce:^(NSString *price, NSString *name, NSNumber *connect){  
    7.                                    return @(price.length > 0 && name.length > 0 && ![connect boolValue]);  
    8.                                    }]  
    9.                              subscribeNext:^(NSNumber *res){  
    10.                                  if ([res boolValue]) {  
    11.                                      NSLog(@"XXXXX send request");  
    12.                                  }  
    13.                              }];  

    例3. 类似于生成产-消费

    场景:用户每次在TextField中输入一个字符,1秒内没有其它输入时,去发一个请求。TextField中字符改变触发事件已在例1中展示,这里实现一下它触法的方法,把1秒延时在此方法中实现。

    实现:

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. - (void)showLoading {  
    2.   
    3.     [self.loadingDispose dispose];//上次信号还没处理,取消它(距离上次生成还不到1秒)  
    4.     @weakify(self);  
    5.     self.loadingDispose = [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {  
    6.         [subscriber sendCompleted];  
    7.         return nil;  
    8.     }] delay:1] //延时一秒  
    9.     subscribeCompleted:^{  
    10.         @strongify(self);  
    11.         doRequest();  
    12.         self.loadingDispose = nil;  
    13.     }];  
    14. }  


    上面代码看起来挻费解,不过下面一段类似的代码拆开写的,会比较容易理解:

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. [self.loadingDispose dispose];  
    2.       
    3.     RACSignal *loggingSignal = [RACSignal createSignal:^ RACDisposable * (id<RACSubscriber> subscriber) {//BLOCK_1  
    4.         subscriptions++;  
    5.         [subscriber sendNext:@"mytest"];  
    6.         [subscriber sendCompleted];  
    7.         return nil;  
    8.     }];  
    9.       
    10.     loggingSignal = [loggingSignal delay:10];  
    11.       
    12.     self.loadingDispose = [loggingSignal subscribeNext:^(NSString* x){//BLOCK_2  
    13.         NSLog(@"%@",x);  
    14.         NSLog(@"subscription %u", subscriptions);  
    15.     }];  
    16.       
    17.     self.loadingDispose = [loggingSignal subscribeCompleted:^{//BLOCK_3  
    18.         NSLog(@"subscription %u", subscriptions);  
    19.     }];  

    loggingSignal在每次被调用subscriibeNext:^(id x)或subscribeCompleted:^方法时(12行和17行),它创建进传进的参数block_1就会被触动发,而block_1中的sendNext:方法会调用subscriibeNext:^中对应的block_2, 而block_1中的sendCompleted会调用subscribeCompleted:中对应的block_3

  • 相关阅读:
    luogu P1833 樱花 看成混合背包
    luogu P1077 摆花 基础记数dp
    luogu P1095 守望者的逃离 经典dp
    Even Subset Sum Problem CodeForces
    Maximum White Subtree CodeForces
    Sleeping Schedule CodeForces
    Bombs CodeForces
    病毒侵袭持续中 HDU
    病毒侵袭 HDU
    Educational Codeforces Round 35 (Rated for Div. 2)
  • 原文地址:https://www.cnblogs.com/tangyuanby2/p/6211399.html
Copyright © 2011-2022 走看看