RAC - 映射(Map & flattenMap)

文章系列
《ReactiveCocoa 概述》
《RACSignal》
《RACDisposable》
《RACSubject、RACReplaySubject(内附冷信号和热信号的区别)》
《集合RACTuple、RACSequence》
《RAC 中的通知、代理、KVO, 基本事件、方法的监听》
《rac_liftSelector》
《RACMulticastConnection》
《RACCommand》
《RAC - 核心方法bind》
《RAC - 定时器》
《RACScheduler》
《RAC - 点击获取验证码 demo》
《RAC - 映射(Map & flattenMap)》
《RAC信号操作解释合集》
《RAC - 信号的生命周期》

flattenMapMap 都用于把源信号内容映射成新的内容.

flattenMap

作用: 用于信号中信号,把源信号的内容映射成一个新的信号,信号可以是任意类型

flattenMap使用步骤:

  • 传入一个block, block 类型是返回值RACStream,参数value.
  • 参数value 就是源信号的内容, 拿到源信号的内容做处理.
  • 包装成RACReturnSignal 信号,返回出去.
- (void)flatteMapTest {
    
    // 创建信号
    RACSubject *subject = [RACSubject subject];
    
    // 绑定信号
    RACSignal *bindSignal = [subject flattenMap:^__kindof RACSignal * _Nullable(id  _Nullable value) {
        
        // value: 源信号发送的内容
        value = [NSString stringWithFormat:@"flattenMap 后的信号:%@", value];
        
        // 返回的信号:用来包装成修改内容值
        return [RACReturnSignal return:value];
    }];
                             
    // flattenMap中返回的是什么信号,订阅的就是什么信号
    // 订阅信号
    [bindSignal subscribeNext:^(id x) {
        
        NSLog(@"%@", x);
    }];
    
    // 发送数据
    [subject sendNext:@1];
}
打印结果

flattenMap底层实现:

  1. flattenMap内部调用bind方法实现的, flattenMapblock的返回值,会作为bindbindBlock的返回值.
  2. 当订阅绑定信号,就会生成bindBlock.
  3. 当源信号发送内容,就会调用bindBlock(value, *stop).
  4. 调用bindBlock, 内部就会调用flattenMapblock, flattenMapblock作用:就是把处理好的数据包装成信号.
  5. 返回的信号最终会作为bindBlock中的返回信号,当做bindBlock的返回信号.
  6. 订阅bindBlock的返回信号,就会拿到绑定信号的订阅者,把处理完成的信号内容发送出来.
- (__kindof RACStream *)flattenMap:(__kindof RACStream * (^)(id value))block {
    Class class = self.class;

    return [[self bind:^{
        return ^(id value, BOOL *stop) {
            id stream = block(value) ?: [class empty];
            NSCAssert([stream isKindOfClass:RACStream.class], @"Value returned from -flattenMap: is not a stream: %@", stream);

            return stream;
        };
    }] setNameWithFormat:@"[%@] -flattenMap:", self.name];
}

Map

作用: 把源信号的值映射成一个新的值

Map使用步骤:

  • 传入一个block, 类型是返回对象, 参数是value.
  • value 就是源信号的内容,直接拿到源信号的内容做处理.
  • 把处理好的内容,直接返回就好了,不用包装成信号,返回的值,就是映射的值.
- (void)mapTest {
    
    RACSubject *subject = [RACSubject subject];
    
    RACSignal *Signal = [subject map:^id _Nullable(NSNumber *value) {
        
        value = @(value.integerValue + 1);
        return value;
    }];
    
    [Signal subscribeNext:^(id  _Nullable x) {
       
        NSLog(@"%@", x);
    }];
    
    [subject sendNext:@1];
}

信号subject发送的是1, 但是Map内部的操作是将所有发送的值做加一操作, 多以打印结果为2

打印结果

Map底层实现:

  1. Map底层其实是调用flatternMap,Mapblock中的返回的值会作为flatternMapblock中的值.
  2. 当订阅绑定信号, 就会生成bindBlock.
  3. 当源信号发送内容,就会调用bindBlock(value, *stop).
    4.调用bindBlock,内部就会调用flattenMapblock.
  4. flattenMapblock内部会调用Map中的block,把Map中的block返回的内容包装成返回的信号.
  5. 返回的信号最终会作为bindBlock中的返回信号,当做bindBlock的返回信号.
  6. 订阅bindBlock的返回信号,就会拿到绑定信号的订阅者,把处理完成的信号内容发送出来.

FlatternMap和Map的区别

1. FlatternMap 中的Block 返回信号.
2. Map 中的Block 返回对象.
3. 开发中,如果信号发出的值不是信号,映射一般使用Map.
4. 开发中,如果信号发出的值是信号,映射一般使用FlatternMap.

FlatternMap直接处理信号中的信号示例:

- (void)flattenMapTest2{

    RACSubject *signalOfsignals = [RACSubject subject];
    
    RACSubject *signal1 = [RACSubject subject];
    RACSubject *signal2 = [RACSubject subject];

    [[signalOfsignals flattenMap:^__kindof RACSignal * _Nullable(id  _Nullable value) {
        
        // 当signalOfsignals的signals发出信号才会调用
        return value;
    }] subscribeNext:^(id  _Nullable x) {
        
        // 只有signalOfsignals 的signal 发出信号才会调用,
        // 也就是flattenMap返回的信号(上面的value)发出内容,才会调用。
        NSLog(@"x=%@",x);
    }];
      
    // 信号的信号发送信号
    [signalOfsignals sendNext:signal1];
    [signalOfsignals sendNext:signal2];

    // 信号发送内容
    [signal1 sendNext:@1];
    [signal1 sendNext:@2];
    [signal2 sendNext:@3];
}
打印结果
注:

高阶信号使用switchToLatest , 关注的是高阶信号中的最后一个信号.
高阶信号使用flattenMap, 是把整个高阶信号扁平化, 得到一个低阶信号.

.End

你可能感兴趣的:(RAC - 映射(Map & flattenMap))