IOS响应式编程框架ReactiveCocoa(RAC)使用示例



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


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

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

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

实现: 

?
1
2
3
4
[RACObserve(self, input)
     subscribeNext:^(NSString* x){
         request(x); //发送一个请求
    }];

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

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

实现:

?
1
2
3
4
5
6
7
8
9
10
11
[[RACObserve(self, input)
      filter:^(NSString* value){
          if ([value hasPrefix:@ "2" ]) {
              return YES;
          } else {
              return NO;
          }
      }]
      subscribeNext:^(NSString* x){
         request(x); //发送一个请求
     }];

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

实现:

?
1
2
3
4
5
6
7
8
9
10
[[self.priceInput.rac_textSignal
      filter:^(NSString *str) {
          if (str.integerValue > 20 ) {
              return YES;
          } else {
              return NO;
          }
      }]
      subscribeNext:^(NSString *str) {
<span style= "white-space:pre" >  </span>request(x); //发送一个请求
}];

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

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

实现:

?
1
2
3
4
5
6
7
8
RAC(self.payButton,enabled) = [RACSignal
                                    combineLatest:@[self.priceInput.rac_textSignal,
                                                 self.nameInput.rac_textSignal,
                                                 RACObserve(self, isConnected)
                                                 ]
                                    reduce:^(NSString *price, NSString *name, NSNumber *connect){
                                    return @(price.length > 0 && name.length > 0 && [connect boolValue]);
                                    }];

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

实现:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
[[RACSignal
                                    combineLatest:@[self.priceInput.rac_textSignal,
                                                 self.nameInput.rac_textSignal,
                                                 RACObserve(self, isConnected)
                                                 ]
                                    reduce:^(NSString *price, NSString *name, NSNumber *connect){
                                    return @(price.length > 0 && name.length > 0 && ![connect boolValue]);
                                    }]
                              subscribeNext:^(NSNumber *res){
                                  if ([res boolValue]) {
                                      NSLog(@ "XXXXX send request" );
                                  }
                              }];

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

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

实现:

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[self.loadingDispose dispose];
     
     RACSignal *loggingSignal = [RACSignal createSignal:^ RACDisposable * (id<racsubscriber> subscriber) { //BLOCK_1
         subscriptions++;
         [subscriber sendNext:@ "mytest" ];
         [subscriber sendCompleted];
         return nil;
     }];
     
     loggingSignal = [loggingSignal delay: 10 ];
     
     self.loadingDispose = [loggingSignal subscribeNext:^(NSString* x){ //BLOCK_2
         NSLog(@ "%@" ,x);
         NSLog(@ "subscription %u" , subscriptions);
     }];
     
     self.loadingDispose = [loggingSignal subscribeCompleted:^{ //BLOCK_3
         NSLog(@ "subscription %u" , subscriptions);
     }];</racsubscriber>

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值