ReactiveCocoa入门到实战 学习笔记(一)

ReactiveCocoa操作详解


内容大纲

  • RACSignal使用基础
  • RACSignal各类操作

RACSignal使用基础

1. 获得一个信号
  • 单元信号
RACSignal *signal1 = [RACSignal return:@"Some Value"]; // 创建一个值信号
RACSignal *signal2 = [RACSignal error:errorObject]; // 创建一个错误信号
RACSignal *signal3 = [RACSignal empty]; // 创建一个空信号
RACSignal *signal4 = [RACSignal never]; // 创建一个无尽的信号
  • 动态信号
RACSignal *signal5 = [RACSignal createSignal:^RACDisposable *(id subscriber) {
       
        [subscriber sendNext:@1];
        [subscriber sendNext:@1];
        [subscriber sendNext:@1];
        [subscriber sendError:errorObject];
        [subscriber sendCompleted];
        return [RACDisposable disposableWithBlock:^{
            
            NSLog(@"disposabled");
        }];
    }];
  • Cocoa桥接
RACSignal *signal6 = [view rac_signalForSelector:@selector(setFrame:)];
RACSignal *signal7 = [view rac_signalForControlEvents:UIControlEventTouchUpInside];
RACSignal *signal8 = [view rac_willDeallocSignal];
RACSignal *signal9 = RACObserve(view, currentTitle);
  • 信号变换
RACSignal *signal10 = [signal1 map:^id(id value) {
    return [value substringFromIndex:1];
}];
  • 序列转换
RACSignal *signal11 = @[@1, @2, @3, @4].rac_sequence.signal;
2. 订阅一个信号的方式
  • 订阅方法
RACSignal *signal11 = @[@1, @2, @3, @4].rac_sequence.signal;
[signal11 subscribeNext:^(id x) {
    NSLog(@"next vlaue is %@", x);
} error:^(NSError *error) {
    NSLog(@"Ops! Get some error: %@", error);
} completed:^{
    NSLog(@"It is finished");
}];
  • 绑定
RAC(view, backgroundColor) = signal1;
  • Cocoa桥接
[view rac_liftSelector:@selector(convertPoint:toView:) withSignals:signal1, signal2, nil];
[view rac_liftSelector:@selector(convertPoint:toView:) withSignals:@[signal1, signal2]];
[view rac_liftSelector:@selector(convertPoint:toView:) withSignals:signal5];

RACSignal各类操作

1. 单个信号的变换
1.1 对信号值得操作
  • Map
    map操作可以获取到信号发出的value,通过block返回以得到一个新的信号
    RACSignal *signal12 = [signal11 map:^id(id value) {
        return @([value integerValue] - 1);;
    }];
    [signal12 subscribeNext:^(id x) {
        NSLog(@"%@", x);
    }];

    /*
      2021-08-03 22:29:42.269178+0800 RACTestOne[34577:1684307] 0
      2021-08-03 22:29:42.269282+0800 RACTestOne[34577:1684307] 1
      2021-08-03 22:29:42.269386+0800 RACTestOne[34577:1684307] 2
      2021-08-03 22:29:42.269524+0800 RACTestOne[34577:1684307] 3
    */
  • MapReplace
    将所有的信号返回替换为一个新的对象,是map的简易版
RACSignal *signal13 = [signal12 mapReplace:@1];
  • ReduceEach
    取出元祖信号中的每一个值,并返回一个新的值
RACSignal *signal1 = [RACSignal createSignal:^RACDisposable *(id subscriber) {
        
        [subscriber sendNext:RACTuplePack(@1, @2, @3)];
        [subscriber sendNext:RACTuplePack(@2, @3)];
        [subscriber sendNext:RACTuplePack(@3, @4)];
        [subscriber sendNext:RACTuplePack(@4, @5)];
        
        [subscriber sendCompleted];
        
        return nil;
    }];
    
    
    RACSignal *signal2 = [signal1 reduceEach:^NSNumber *(NSNumber *first, NSNumber *second, NSNumber *third){
        
        return @(first.integerValue + second.integerValue + third.integerValue);
    }];
    
    [signal2 subscribeNext:^(id x) {
        NSLog(@"%@", x);
    }];
    
    /*
    2021-08-04 08:42:10.251210+0800 RACTestOne[34956:1706970] 6
    2021-08-04 08:42:10.251318+0800 RACTestOne[34956:1706970] 5
    2021-08-04 08:42:10.251403+0800 RACTestOne[34956:1706970] 7
    2021-08-04 08:42:10.251457+0800 RACTestOne[34956:1706970] 9
     */

可以看到,当元祖数量不同时,reduceEach会将取不到的值设置为 nil 而不会出现崩溃。

  • not
    对一个仅返回BOOL类型的信号取反
    RACSignal *signal3 = [RACSignal return:@YES];
    [[signal3 not] subscribeNext:^(id x) {
       
        NSLog(@"%@", [x boolValue] ? @"YES" : @"NO");
    }];
    
    /*
     2021-08-04 08:47:17.944753+0800 RACTestOne[35009:1710481] NO
     */
  • and
    对一个发送了一个或多个长度不为零的元祖的信号,且元祖内部的值全都是由布尔值组成的,将每个元祖内的所有值做与操作,返回结果。
  • or
    对一个发送了一个或多个长度不为零的元祖的信号,且元祖内部的值全都是由布尔值组成的,将每个元祖内的所有值做或操作,返回结果。
    RACSignal *signal3 = [RACSignal return:RACTuplePack(@YES, @NO, @YES)];
    [[signal3 and] subscribeNext:^(id x) {
       
        NSLog(@"AND: %@", [x boolValue] ? @"YES" : @"NO");
    }];
    
    [[signal3 or] subscribeNext:^(id x) {
       
        NSLog(@"OR: %@", [x boolValue] ? @"YES" : @"NO");
    }];
    
    /*
     2021-08-04 08:58:21.128811+0800 RACTestOne[35195:1719493] AND: NO
     2021-08-04 08:58:21.128980+0800 RACTestOne[35195:1719493] OR: YES
     */
  • reduceApply
    reduceApply需要对一个合并信号做处理,第一个信号返回一个处理后面几个信号发送值得处理函数Block,后面几个信号返回等待被处理的数值。
    RACSignal *adder = [RACSignal return:^NSNumber *(NSNumber *one, NSNumber *two, NSNumber *three) {
       
        return @([one integerValue] + [two integerValue] + [three integerValue]);
    }];
    
    RACSignal *as = [RACSignal return:@1];
    RACSignal *bs = [RACSignal return:@2];
    RACSignal *cs = [RACSignal return:@3];
    
    [[[RACSignal combineLatest:@[adder, as, bs, cs]] reduceApply] subscribeNext:^(id x) {
        NSLog(@"%@", x);
    }];
    
    /*
     2021-08-04 09:14:58.073673+0800 RACTestOne[35453:1730815] 6
     */
  • materialize
    返回一个新的信号,原始信号返回的类型被包装成RACEven返回
    RACSignal *adder = [RACSignal return:^NSNumber *(NSNumber *one, NSNumber *two, NSNumber *three) {
       
        return @([one integerValue] + [two integerValue] + [three integerValue]);
    }];
    
    [[adder materialize] subscribeNext:^(id x) {
        NSLog(@"%@", x);
    }];
    
    /*
     2021-08-04 09:19:57.367154+0800 RACTestOne[35556:1734750] { next = <__NSGlobalBlock__: 0x1000c0048> }
     2021-08-04 09:19:57.367420+0800 RACTestOne[35556:1734750] { completed }
     */
  • dematerialize
    对materialize包装过的信号进行解包,将包装成RACEven的信号还原成内部包装的值
    RACSignal *signal3 = [RACSignal return:RACTuplePack(@1, @2, @3)];

    [[[signal3 materialize] dematerialize] subscribeNext:^(id x) {
        NSLog(@"%@", x);
    }];
    
    /*
     2021-08-04 09:23:13.567598+0800 RACTestOne[35639:1738327]  (
         1,
         2,
         3
     )
     */
1.2 对信号数量的操作
  • Filter
    筛选过滤掉部分信号的返回,减少信号返回的数量
    [[@[@1, @2, @3, @4, @5, @6].rac_sequence.signal filter:^BOOL(id value) {
        return [value integerValue] % 2 == 0;
    }] subscribeNext:^(id x) {
        NSLog(@"%@", x);
    }];
    /*
     2021-08-04 09:27:25.854256+0800 RACTestOne[35708:1741471] 2
     2021-08-04 09:27:25.854370+0800 RACTestOne[35708:1741471] 4
     2021-08-04 09:27:25.854520+0800 RACTestOne[35708:1741471] 6
     */
  • Ignore
    忽略掉制定的返回值
    [[@[@1, @2, @3, @4, @5, @6].rac_sequence.signal
      ignore:@2] subscribeNext:^(id x) {
        NSLog(@"%@", x);
    }];
    /*
     2021-08-04 09:28:57.476956+0800 RACTestOne[35736:1742733] 1
     2021-08-04 09:28:57.477062+0800 RACTestOne[35736:1742733] 3
     2021-08-04 09:28:57.477110+0800 RACTestOne[35736:1742733] 4
     2021-08-04 09:28:57.477148+0800 RACTestOne[35736:1742733] 5
     2021-08-04 09:28:57.477264+0800 RACTestOne[35736:1742733] 6
     */
  • ignoreValues
    忽略掉所有的next信号返回
    [[@[@1, @2, @3, @4, @5, @6].rac_sequence.signal ignoreValues] subscribeNext:^(id x) {
        NSLog(@"%@", x);
    }];
  • distinctUntilChanged
    当出现连续的重复项时,只取最后一项返回
    [[@[@1, @1, @2, @2, @3, @2, @4, @5, @6].rac_sequence.signal distinctUntilChanged] subscribeNext:^(id x) {
        NSLog(@"%@", x);
    }];
    /*
     2021-08-04 09:32:14.037896+0800 RACTestOne[35834:1746249] 1
     2021-08-04 09:32:14.037999+0800 RACTestOne[35834:1746249] 2
     2021-08-04 09:32:14.038068+0800 RACTestOne[35834:1746249] 3
     2021-08-04 09:32:14.038108+0800 RACTestOne[35834:1746249] 2
     2021-08-04 09:32:14.038189+0800 RACTestOne[35834:1746249] 4
     2021-08-04 09:32:14.038236+0800 RACTestOne[35834:1746249] 5
     2021-08-04 09:32:14.038291+0800 RACTestOne[35834:1746249] 6
     */
  • Take
    取固定数量的信号返回
    [[@[@1, @1, @2, @2, @3, @2, @4, @5, @6].rac_sequence.signal take:2] subscribeNext:^(id x) {
        NSLog(@"%@", x);
    }];
    /*
     021-08-04 09:38:15.003595+0800 RACTestOne[35907:1749829] 1
     2021-08-04 09:38:15.003683+0800 RACTestOne[35907:1749829] 1
     */
  • Skip
    跳过固定数量的信号
    [[@[@1, @1, @2, @2, @3, @2, @4, @5, @6].rac_sequence.signal skip:2] subscribeNext:^(id x) {
        NSLog(@"%@", x);
    }];
    /*
     2021-08-04 09:39:04.452936+0800 RACTestOne[35945:1750781] 2
     2021-08-04 09:39:04.453019+0800 RACTestOne[35945:1750781] 2
     2021-08-04 09:39:04.453232+0800 RACTestOne[35945:1750781] 3
     2021-08-04 09:39:04.453386+0800 RACTestOne[35945:1750781] 2
     2021-08-04 09:39:04.453442+0800 RACTestOne[35945:1750781] 4
     2021-08-04 09:39:04.453485+0800 RACTestOne[35945:1750781] 5
     2021-08-04 09:39:04.453523+0800 RACTestOne[35945:1750781] 6
     */
  • takeLast
    取最后几个信号
    [[@[@1, @1, @2, @2, @3, @2, @4, @5, @6].rac_sequence.signal takeLast:2] subscribeNext:^(id x) {
        NSLog(@"%@", x);
    }];
    /*
     2021-08-04 09:39:50.624034+0800 RACTestOne[35965:1751667] 5
     2021-08-04 09:39:50.624094+0800 RACTestOne[35965:1751667] 6
     */
  • takeUntilBlock
    根据block判断是否终止取值,如果block返回YES,则终止取值
    [[@[@1, @1, @2, @0, @3, @2, @4, @5, @6].rac_sequence.signal takeUntilBlock:^BOOL(id x) {
        
        return [x integerValue] == 0;
    }] subscribeNext:^(id x) {
        NSLog(@"%@", x);
    }];
    /*
     2021-08-04 09:41:29.019555+0800 RACTestOne[36008:1753297] 1
     2021-08-04 09:41:29.019634+0800 RACTestOne[36008:1753297] 1
     2021-08-04 09:41:29.019721+0800 RACTestOne[36008:1753297] 2
     */
  • takeWhileBlock
    与takeUntilBlock相反,返回YES时继续取值,返回NO时终止取值
    [[@[@1, @1, @2, @0, @3, @2, @4, @5, @6].rac_sequence.signal takeWhileBlock:^BOOL(id x) {
        
        return [x integerValue] != 0;
    }] subscribeNext:^(id x) {
        NSLog(@"%@", x);
    }];
    /*
     2021-08-04 09:41:29.019555+0800 RACTestOne[36008:1753297] 1
     2021-08-04 09:41:29.019634+0800 RACTestOne[36008:1753297] 1
     2021-08-04 09:41:29.019721+0800 RACTestOne[36008:1753297] 2
     */
  • skipUntilBlock

  • skipWhileBlock
    同理

  • any
    收到任何信号时,返回一个YES

  • any:
    根据block,遍历判断每一个信号,直到找到符合条件的信号则返回YES,如果一直没有则返回 NO

  • all:
    遍历查找,出现第一个不符合block条件的数值则返回NO,所有数值都符合则返回YES

   [[@[@2, @1, @2, @3, @5].rac_sequence.signal all:^BOOL(id object) {
        
        NSInteger result = [object integerValue] % 2;
        return result == 0;
        
    }] subscribeNext:^(id x) {
        NSLog(@"%@", x);
    }];
  • startWith
    往头部添加一个信号
  • repeat
    对信号无限重播
  • retry:
    遇到错误时进行重试,参数为重试的次数
  • collect
    将所有收到的信号打包成一个数组,一次性返回
  • Aggregate
    折叠函数,对每个信号根据block规则进行折叠,最终一次性返回
    [[@[@2, @1, @2, @3, @5].rac_sequence.signal
      aggregateWithStart:@0 reduce:^id(id running, id next) {
        
        return @([running integerValue] + [next integerValue]);
        
    }] subscribeNext:^(id x) {
        NSLog(@"%@", x);
    }];
    /*
     2021-08-04 10:54:45.216450+0800 RACTestOne[36763:1783653] 13
     */
  • scan:
    扫描函数,也会对信号进行折叠,但是每一次的折叠计算都会被返回
    [[@[@2, @1, @2, @3, @5].rac_sequence.signal
      scanWithStart:@0 reduce:^id(id running, id next) {
        
        return @([running integerValue] + [next integerValue]);
        
    }] subscribeNext:^(id x) {
        NSLog(@"%@", x);
    }];
    /*
     2021-08-04 10:55:51.862320+0800 RACTestOne[36810:1785060] 2
     2021-08-04 10:55:51.862408+0800 RACTestOne[36810:1785060] 3
     2021-08-04 10:55:51.862454+0800 RACTestOne[36810:1785060] 5
     2021-08-04 10:55:51.862511+0800 RACTestOne[36810:1785060] 8
     2021-08-04 10:55:51.862568+0800 RACTestOne[36810:1785060] 13
     */
  • aggregateWithStartFactory
    与Aggregate功能相同,只是start是通过外接一个block返回的
1.3 对信号维度的操作
  • contact
    组合多个信号,一个信号结束以后再执行下一个信号
    RACSignal *signal = [[@[@1,@1,@1, @2, @3, @4, @5].rac_sequence.signal map:^id(id value) {
        
        return [[RACSignal return:value] delay:[value doubleValue]];
    }] concat];
    [signal subscribeNext:^(id x) {
        NSLog(@"%@-%@",x, [NSDate date]);
    }];
    /*
     2021-08-04 11:17:51.630939+0800 RACTestOne[37128:1799867] 1-Wed Aug  4 11:17:51 2021
     2021-08-04 11:17:52.730100+0800 RACTestOne[37128:1799868] 1-Wed Aug  4 11:17:52 2021
     2021-08-04 11:17:53.741029+0800 RACTestOne[37128:1799868] 1-Wed Aug  4 11:17:53 2021
     2021-08-04 11:17:55.843420+0800 RACTestOne[37128:1799867] 2-Wed Aug  4 11:17:55 2021
     2021-08-04 11:17:59.060781+0800 RACTestOne[37128:1799866] 3-Wed Aug  4 11:17:59 2021
     2021-08-04 11:18:03.399525+0800 RACTestOne[37128:1799867] 4-Wed Aug  4 11:18:03 2021
     2021-08-04 11:18:08.747093+0800 RACTestOne[37128:1799991] 5-Wed Aug  4 11:18:08 2021
     */

可以看到,每个信号都等待到了信号延时结束。

  • Merge
    两个信号被组合成了一个信号,并依照时间轴交替执行
    RACSignal *signal1 = [@[@1, @3,@5].rac_sequence.signal map:^id(id value) {
        
        return [[RACSignal return:value] delay:[value doubleValue]];
    }];
    RACSignal *signal2 = [@[@2, @4, @6].rac_sequence.signal map:^id(id value) {
        
        return [[RACSignal return:value] delay:[value doubleValue]];
    }];
    RACSignal *signal3 = [[signal1 merge:signal2] flatten];
    [signal3 subscribeNext:^(id x) {
        NSLog(@"%@-%@",x, [NSDate date]);
    }];
    /*
     2021-08-04 11:22:05.839697+0800 RACTestOne[37210:1803227] 1-Wed Aug  4 11:22:05 2021
     2021-08-04 11:22:06.826184+0800 RACTestOne[37210:1803227] 2-Wed Aug  4 11:22:06 2021
     2021-08-04 11:22:07.926575+0800 RACTestOne[37210:1803227] 3-Wed Aug  4 11:22:07 2021
     2021-08-04 11:22:08.940237+0800 RACTestOne[37210:1803225] 4-Wed Aug  4 11:22:08 2021
     2021-08-04 11:22:09.954859+0800 RACTestOne[37210:1803227] 5-Wed Aug  4 11:22:09 2021
     2021-08-04 11:22:11.038293+0800 RACTestOne[37210:1803225] 6-Wed Aug  4 11:22:11 2021
     */
  • zip
    将A,B两个信号组成一个元祖信号,并且严格执行(A,B)(A, B)模式,两个信号的返回必须成对,无法组队的信号不返回
    RACSignal *signal1 = [[@[@1, @3,@5].rac_sequence.signal map:^id(id value) {
        
        return [[RACSignal return:value] delay:[value doubleValue]];
    }] flatten];
    RACSignal *signal2 = [[@[@2, @4].rac_sequence.signal map:^id(id value) {
        
        return [[RACSignal return:value] delay:[value doubleValue]];
    }] flatten];
    RACSignal *signal3 = [signal1 zipWith:signal2];
    [signal3 subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];
    /*
     2021-08-04 11:27:42.739708+0800 RACTestOne[37338:1809066]  (
         1,
         2
     )
     2021-08-04 11:27:44.976464+0800 RACTestOne[37338:1809066]  (
         3,
         4
     )
     */
  • combineLatest
    与zip类似,组合两个信号,但是不需要强制成对。A,B信号任意信号返回新值时,就会触发信号的订阅回调
    RACSignal *signal1 = [[@[@1, @3,@5].rac_sequence.signal map:^id(id value) {
        
        return [[RACSignal return:value] delay:[value doubleValue]];
    }] concat];
    RACSignal *signal2 = [[@[@2, @4].rac_sequence.signal map:^id(id value) {
        
        return [[RACSignal return:value] delay:[value doubleValue]];
    }] concat];
    RACSignal *signal3 = [signal1 combineLatestWith:signal2];
    [signal3 subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];
    /*
     2021-08-04 11:29:32.056260+0800 RACTestOne[37397:1811166]  (
         1,
         2
     )
     2021-08-04 11:29:34.118925+0800 RACTestOne[37397:1811169]  (
         3,
         2
     )
     2021-08-04 11:29:36.445053+0800 RACTestOne[37397:1811166]  (
         3,
         4
     )
     2021-08-04 11:29:39.342934+0800 RACTestOne[37397:1811169]  (
         5,
         4
     )
     */
  • sample
    取样,根据取样信号,取出当前信号对应取样节点时返回的值。
    RACSignal *arraySignal = [@[@1, @2, @3, @4, @5, @6, @8, @10, @0].rac_sequence.signal flattenMap:^RACStream *(id value) {
        
        return [[RACSignal return:value] delay:[value doubleValue]];
    }];
    
    RACSignal *timeSignal = [RACSignal interval:2 onScheduler:[RACScheduler scheduler]];
    
    [[arraySignal sample:timeSignal] subscribeNext:^(id x) {
       
        NSLog(@"%@", x);
    }];

    /*
     2021-08-04 11:48:31.610566+0800 RACTestOne[37677:1825278] 1
     2021-08-04 11:48:33.609945+0800 RACTestOne[37677:1825280] 3
     2021-08-04 11:48:35.610757+0800 RACTestOne[37677:1825280] 5
     2021-08-04 11:48:37.610773+0800 RACTestOne[37677:1825278] 6
     2021-08-04 11:48:39.610739+0800 RACTestOne[37677:1825278] 8
     */
1.4 对信号时间的操作
  • + (RACSignal *)interval:(NSTimeInterval)interval onScheduler:(RACScheduler *)scheduler;
  • + (RACSignal *)interval:(NSTimeInterval)interval onScheduler:(RACScheduler *)scheduler withLeeway:(NSTimeInterval)leeway;
    返回一个定时器信号
  • Delay
    对信号的发送时机进行延时
    RACSignal *signal = [RACSignal interval:1 onScheduler:[RACScheduler scheduler]];
    RACSignal *signa2 = [signal delay: 1];
  • Throttle
    阀门,一定时间内连续出现信号时,只取其最后一个信号。
    RACSignal *signal = [[@[@1,@1,@1, @2, @3, @4, @5].rac_sequence.signal map:^id(id value) {
        
        return [[RACSignal return:value] delay:[value doubleValue]];
    }] concat];
    [[signal throttle:3] subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];
    /*
     2021-08-04 11:14:02.913663+0800 RACTestOne[37056:1797195] 2
     2021-08-04 11:14:06.140407+0800 RACTestOne[37056:1797195] 3
     2021-08-04 11:14:10.474246+0800 RACTestOne[37056:1797195] 4
     2021-08-04 11:14:12.734156+0800 RACTestOne[37056:1797195] 5
     */

你可能感兴趣的:(ReactiveCocoa入门到实战 学习笔记(一))