首页 > 系统 > iOS > 正文

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

2019-11-09 18:55:27
字体:
来源:转载
供稿:网友

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上查看代码片[RACObserve(self, input)      subscribeNext:^(NSString* x){          request(x);//发送一个请求     }];  

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

 

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

实现:

[objc] view%20plain copy [[RACObserve(self, input)       filter:^(NSString* value){           if ([value hasprefix:@"2"]) {               return YES;           } else {               return NO;           }       }]       subscribeNext:^(NSString* x){          request(x);//发送一个请求      }];  场景:上面场景是监听自己的成员变量,如果想监听UITextField输入值变化,框架也做了封装可以代替系统回调

实现:

[objc] view%20plain copy [[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);//发送一个请求  }];

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

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

实现:

 

[objc] view%20plain copy 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]);                                     }];  

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

实现:

[objc] view%20plain copy [[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.%20类似于生成产-消费

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

实现:

[objc] view%20plain copy - (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;      }];  }  上面代码看起来挻费解,不过下面一段类似的代码拆开写的,会比较容易理解:

[objc] view%20plain copy 派生到我的代码片[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);      }];  

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


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表