iOS ReactiveObjC使用详解

项目地址:ReactiveObjC

1.键值观察--监听TF的值发生变化

- (void)demo1{
  @weakify(self);
  [self.tF.rac_textSignal subscribeNext:^(NSString *value) {
      @strongify(self);
    
      self.value = value;
    
    
  }];

  //当self.value的值变化时调用Block,这是用KVO的机制,RAC封装了KVO

  [RACObserve(self, value) subscribeNext:^(NSString *value) {
    
      NSLog(@"%@",value);
    
  }];
}

2. map的使用

- (void)demo2{
 //创建一个信号
  RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
     //这个信号里面有一个Next事件的玻璃球和一个complete事件的玻璃球
      [subscriber sendNext:@"唱歌"];
      [subscriber sendCompleted];
      return nil;

  }];

  //对信号进行改进,当信号里面流的是唱歌.就改进为'跳舞'返还给self.value

  RAC(self, tF.text) = [signalA map:^id(NSString *value) {
      if ([value isEqualToString:@"唱歌"]) {
         return @"跳舞";
      }
      return @"";
    
  }];       
}

3.filter使用,你向西,他就向东,他向左,你就向右。

- (void)demo3{

  //创建两个通道,一个从A流出的通道A,和一个从B流出的通道B
  RACChannelTerminal *channelA = RACChannelTo(self, value);
  RACChannelTerminal *channelB = RACChannelTo(self,value2);

  //改造通道A,使通过通道A的值,如果等于'西',就改为'东'
  [[channelA map:^id(NSString *value) {
      if ([value isEqualToString:@"西"]) {
          NSLog(@"东");
          return @"东";
        
      }
      NSLog(@"====== %@",value);
      return value;
  }] subscribe:channelB];//通道A流向B

  //改造通道B,使通过通道B的值,如果等于'左',就改为'右'传出去
  [[channelB map:^id(id value) {
      if ([value isEqualToString:@"左"]) {
          NSLog(@"右");
          return @"右";
      }
      NSLog(@"====== %@",value);
     return value;
    
  }] subscribe:channelA];//通道B流向通道A

  //KVO监听valueA的值的变化,过滤valueA的值,返回Yes表示通过
  //只有value有值,才可通过
  [[RACObserve(self, value) filter:^BOOL(id value) {
   
      return value ? YES : NO;
    
  }] subscribeNext:^(id x) {
    
      NSLog(@"你向%@",x);
    
  }];

  //KVO监听value2的变化
  [[RACObserve(self, value2) filter:^BOOL(id value) {
      return value ? YES: NO;
  }] subscribeNext:^(id x) {
      NSLog(@"他向%@",x);
  }];

  //下面使value的值和value2的值发生改变
  self.value = @"西";
  self.value2 = @"左";  
}

4.代理

/**
 *  RACSubject:信号提供者,自己可以充当信号,又能发送信号
 创建方法:
 1.创建RACSubject
 2.订阅信号
 3.发送信号
 工作流程:
 1.订阅信号,内部保存了订阅者,和订阅者相应block
 2.当发送信号的,遍历订阅者,调用订阅者的nextBolck

 注:如果订阅信号,必须在发送信号之前订阅信号,不然收不到信号,有利用区别RACReplaySubject

 */

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
  RacSubjectController *racsub = [[RacSubjectController alloc] init];
  racsub.subject = [RACSubject subject];
  [racsub.subject subscribeNext:^(id x) {
      NSLog(@"被通知了%@",x);
  }];
  [self.navigationController pushViewController:racsub animated:YES];

}

在RacSubjectController.h里面声明属性

@property (nonatomic, strong) RACSubject *subject;

.m里面进行数据的传递

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

  if (self.subject) {
    [self.subject sendNext:@1];

  }

}

5.广播

//发送通知
- (void)demo5{
  NSNotificationCenter *center = [NSNotificationCenter defaultCenter];

  //发送广播通知
  [center postNotificationName:@"妇女之友" object:nil userInfo:@{@"技巧":@"用心听"}];


}

//接收通知

NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
//RAC的通知不需要我们手动移除
//注册广播通知
RACSignal *siganl = [center rac_addObserverForName:@"妇女之友" object:nil];
//设置接收通知的回调处理
[siganl subscribeNext:^(NSNotification *x) {

  NSLog(@"技巧: %@",x.userInfo[@"技巧"]);
}];

6.两个信号串联,两个管串联,一个管处理完自己的东西,下一个管才开始处理自己的东西

- (void)demo6{

  //创建一个信号管A
  RACSignal *siganlA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
      [subscriber sendNext:@"吃饭"];
      [subscriber sendCompleted];
      return nil;
    
  }];

  //创建一个信号管B
  RACSignal *siganlB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
   
      [subscriber sendNext:@"吃的饱饱的,才可以睡觉的"];
      [subscriber sendCompleted];
      return nil;
  }];

  //串联管A和管B
  RACSignal *concatSiganl = [siganlA concat:siganlB];
  //串联后的接收端处理 ,两个事件,走两次,第一个打印siggnalA的结果,第二次打印siganlB的结果
  [concatSiganl subscribeNext:^(id x) {
      NSLog(@"%@",x);
    
  }];

}

7.并联,只要有一个管有东西,就可以打印

- (void)demo7{
  //创建信号A
  RACSignal *siganlA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
    [subscriber sendNext:@"纸厂污水"];
    [subscriber sendCompleted];
    return nil;
  }];

  //创建信号B
  RACSignal *siganlB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
   
    [subscriber sendNext:@"电镀厂污水"];
    [subscriber sendCompleted];
    return nil;
  }];

  //并联两个信号,根上面一样,分两次打印
  RACSignal *mergeSiganl = [RACSignal merge:@[siganlA,siganlB]];
  [mergeSiganl subscribeNext:^(id x) {
   
    NSLog(@"%@",x);
    
  }];

}

8.组合,只有两个信号都有值,才可以组合

- (void)demo8{
  //定义2个自定义信号
  RACSubject *letters = [RACSubject subject];
  RACSubject *numbers = [RACSubject subject];

  //组合信号
  [[RACSignal combineLatest:@[letters,numbers] reduce:^(NSString *letter, NSString *number){
    
      return [letter stringByAppendingString:number];
  }] subscribeNext:^(id x) {
      NSLog(@"%@",x);
    
  }];


  //自己控制发生信号值
  [letters sendNext:@"A"];
  [letters sendNext:@"B"];
  [numbers sendNext:@"1"]; //打印B1
  [letters sendNext:@"C"];//打印C1
  [numbers sendNext:@"2"];//打印C2



}

9.合流压缩

- (void)demo9{

 //创建信号A
  RACSignal *siganlA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
   
      [subscriber sendNext:@"红"];
      [subscriber sendCompleted];
      return nil;
  }];

  //创建信号B
  RACSignal *siganlB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
   
      [subscriber sendNext:@"白"];
      [subscriber sendCompleted];
      return nil;
  }];

  //合流后处理的是压缩包,需要解压后才能取到里面的值
  [[siganlA zipWith:siganlB] subscribeNext:^(id x) {
   
      //解压缩
      RACTupleUnpack(NSString *stringA, NSString *stringB) = x;
      NSLog(@"%@ %@",stringA, stringB);
  }];

}

10.映射,我可以点石成金

- (void)demo10{
  RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
      [subscriber sendNext:nil];
      [subscriber sendCompleted];
      return nil;
  }];
  //对信号进行改造,改"石"成"金"
  siganl = [siganl map:^id(NSString *value) {
      if ([value isEqualToString:@"石"]) {
          return @"金";
      }
      return value;
    
  }];

  //打印,不论信号发送的是什么,这一步都会走的
  [siganl subscribeNext:^(id x) {
      NSLog(@"%@",x);
    
  }];


}

11.过滤,未满18岁,禁止入内

- (void)demo11{
  RACSignal *singal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
   
      [subscriber sendNext:@(15)];
      [subscriber sendNext:@(17)];
      [subscriber sendNext:@(21)];
      [subscriber sendNext:@(14)];
      [subscriber sendNext:@(30)];
    
      [subscriber sendCompleted];
    
      return nil;
  }];

  //过滤信号,打印
  [[singal filter:^BOOL(NSNumber *value) {
    
      //大于18岁的,才可以通过
      return value.integerValue >= 18;//return为yes可以通过
  }] subscribeNext:^(id x) {
      NSLog(@"%@",x);
    
  }];

}

12.秩序(flattenMap方法也可以换成then方法,效果一样)

-(void)demo12{

  RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
      NSLog(@"打蛋液");
      [subscriber sendNext:@"蛋液"];
      [subscriber sendCompleted];
      return nil;
    
  }];

  //对信号进行秩序秩序的第一步
  siganl = [siganl flattenMap:^RACStream *(NSString *value) {
     //处理上一步的RACSiganl的信号value.这里的value=@"蛋液"
      NSLog(@"把%@倒进锅里面煎",value);
      return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
          [subscriber sendNext:@"煎蛋"];
          [subscriber sendCompleted];
          return nil;
        
      }];
    
   }];
  //对信号进行第二步处理
  siganl = [siganl flattenMap:^RACStream *(id value) {
      NSLog(@"把%@装载盘里",value);
      return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
          [subscriber sendNext:@"上菜"];
          [subscriber sendCompleted];
          return nil;
      }];
    
  }];

 //最后打印 最后带有===上菜
  [siganl subscribeNext:^(id x) {
      NSLog(@"====%@",x);
  }];

}

13.命令

-(void)demo13{

  RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
      //打印:今天我投降了

     //命令执行代理
      NSLog(@"%@我投降了",input);
      //返回一个RACSignal信号
      return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
          return nil;
      }];
    
  }];

  //执行命令
  [command execute:@"今天"];


}

14.延迟

- (void)demo14{
  RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
      NSLog(@"等等我,我还有10s就到了");
      [subscriber sendNext:@"北极"];
      [subscriber sendCompleted];
      return nil;
  }];

  //延迟10s接受next的玻璃球
  [[siganl delay:10] subscribeNext:^(id x) {
   
     NSLog(@"我到了%@",x);
    
  }];


}

15.重放

- (void)demo15{

  RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
      NSLog(@"电影");
      [subscriber sendNext:@"电影"];
      [subscriber sendCompleted];
      return nil;
    
  }];

  //创建该普通信号的重复信号
  RACSignal *replaySiganl = [siganl replay];
  //重复接受信号
  [replaySiganl subscribeNext:^(NSString *x) {
      NSLog(@"小米%@",x);
  }];
  [replaySiganl subscribeNext:^(NSString *x) {
      NSLog(@"小红%@",x);
    
  }];
}

16.定时---每隔8小时服用一次药

- (void)demo16{
  //创建定时器信号.定时8小时
  RACSignal *siganl = [RACSignal interval:60 * 60 * 8 onScheduler:[RACScheduler mainThreadScheduler]];
  //定时器执行代码
 [siganl subscribeNext:^(id x) {
      NSLog(@"吃药");
    
  }];


}

17.超时

- (void)demo17{

 RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
      NSLog(@"我快到了");
      RACSignal *sendSiganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
       
          [subscriber sendNext:nil];
          [subscriber sendCompleted];
          return nil;
      }];
    
      //发生信号要1个小时10分钟才到
      [[sendSiganl delay:60 * 70] subscribeNext:^(id x) {
         //这里才发送next玻璃球到siganl
          [subscriber sendNext:@"我到了"];
          [subscriber sendCompleted];
        
      }];
      return nil;
    
    
  }];

  [[siganl timeout:60 * 60 onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(id x) {
   
      NSLog(@"等了你一个小时,你一直没来,我走了");
    
  }];

}

18.重试

- (void)demo18{

  __block int failedCount = 0;

  //创建信号
  RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
      if (failedCount < 100) {
          failedCount ++;
          NSLog(@"我失败了");
          [subscriber sendError:nil];
      }else{
          NSLog(@"经历了数百次后,我成功了");
          [subscriber sendNext:nil];

      }
      return nil;
    
  }];

  //重试
  RACSignal *retrySiganl = [siganl retry];
  //直到发生next的玻璃球
  [retrySiganl subscribeNext:^(id x) {
      NSLog(@"重要成功了");
    
  }];

}

19.节流,不好意思,这里每一秒只能通过一个人,如果1s内发生多个,只通过最后一个

- (void)demo19{

  RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
     //即使发送一个next的玻璃球
      [subscriber sendNext:@"A"];
      dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
          [subscriber sendNext:@"B"];
        
      });
      dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
          [subscriber sendNext:@"C"];
          [subscriber sendNext:@"D"];
          [subscriber sendNext:@"E"];
         
     });
      dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
          [subscriber sendNext:@"F"];
      });
      return nil;
    
  }];

  //对信号进行节流,限制时间内一次只能通过一个玻璃球
  [[signal throttle:1] subscribeNext:^(id x) {
      NSLog(@"%@通过了",x);
    
  }];
  /*
   [2015-08-16 22:08:45.677]旅客A
   [2015-08-16 22:08:46.737]旅客B
   [2015-08-16 22:08:47.822]旅客E
   [2015-08-16 22:08:48.920]旅客F
   */

}

20.条件(takeUntil方法,当给定的signal完成前一直取值)

- (void)demo20{

  RACSignal *takeSiganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
     //创建一个定时器信号,每一秒触发一次
      RACSignal *siganl = [RACSignal interval:1 onScheduler:[RACScheduler mainThreadScheduler]];
      [siganl subscribeNext:^(id x) {
         //在这里定时发送next玻璃球
          [subscriber sendNext:@"直到世界尽头"];
        
      }];
      return nil;

  }];

  //创建条件信号
  RACSignal *conditionSiganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
     //设置5s后发生complete玻璃球
      dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
          NSLog(@"世界的今天到了,请下车");
          [subscriber sendCompleted];
      });
      return nil;
  }];

  //设置条件,takeSiganl信号在conditionSignal信号接收完成前,不断取值
  [[takeSiganl takeUntil:conditionSiganl] subscribeNext:^(id x) {
      NSLog(@"%@",x);
    
  }];


}

21.RACReplaySubject使用

/**
 *  RACReplaySubject创建方法
    1.创建RACSubject
    2.订阅信号
    3.发送信号
 工作流程:
   1.订阅信号,内部保存了订阅者,和订阅者相应的block
   2.当发送信号的,遍历订阅者,调用订阅者的nextBlock
   3.发送的信号会保存起来,当订阅者订阅信号的时候,会将之前保存的信号,一个个作用于新的订阅者,保存信号的容量由capacity决定,这也是有别于RACSubject的
 */

-(void)RACReplaySubject{

  RACReplaySubject *replaySubject = [RACReplaySubject subject];
  [replaySubject subscribeNext:^(id x) {
      NSLog(@" 1 %@",x);
  }];

  [replaySubject subscribeNext:^(id x) {
      NSLog(@"2 %@",x);
  }];
  [replaySubject sendNext:@7];
  [replaySubject subscribeNext:^(id x) {
      NSLog(@"3 %@",x);
  }];

}

22.rac_liftSelector:withSignals使用

//这里的rac_liftSelector:withSignals 就是干这件事的,它的意思是当signalA和signalB都至少sendNext过一次,接下来只要其中任意一个signal有了新的内容,doA:withB这个方法就会自动被触发

-(void)test{

  RACSignal *sigalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
   
      double delayInSeconds = 2.0;
      dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds *NSEC_PER_SEC));
      dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(popTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
          [subscriber sendNext:@"A"];
        
      });
      return nil;
  }];

  RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
      [subscriber sendNext:@"B"];
      [subscriber sendNext:@"Another B"];
      [subscriber sendCompleted];
      return nil;
    
  }];
  [self rac_liftSelector:@selector(doA:withB:) withSignals:sigalA,signalB, nil];

}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容

  • RAC在iOS的实际开发中确实是一件有力的武器,此文将从以下几方面讲解 RACSignal RACSubject ...
    4b5cb36a2ee2阅读 882评论 0 0
  • 一、RAC简介 ReactiveCocoa(简称为RAC),是由Github开源的一个应用于iOS和OS开发的新框...
    yahoouchen阅读 5,863评论 0 21
  • 新项目今天提测,项目中用到了RAC&MVVM框架,简单记录下RAC的简单使用 项目是OC开发,用的是Reactiv...
    星辰流转轮回阅读 465评论 0 1
  • 标签: iOS RAC 概述 ReactiveCocoa是一个函数响应式编程框架,它能让我们脱离Cocoa AP...
    GodyZ阅读 7,497评论 16 97
  • 转载自http://www.jianshu.com/p/a4fefb434652一、常见类1、RACSiganl ...
    君莫叹人生如若初见阅读 1,418评论 0 18