RAC总结

作者: LGByte | 来源:发表于2018-11-21 20:04 被阅读0次

    ReactiveCocoa

    ReactiveCocoa

    一 、导入框架

    target 'OneIsAll' do
    pod "AFNetworking", '3.1.0'
    pod "MJRefresh", '3.1.12'
    pod 'MJExtension', '3.0.13'
    pod 'Masonry', '1.0.2'
    pod 'SDWebImage', '3.8.2'
    pod 'ReactiveCocoa', '2.5'
    pod 'SVProgressHUD', '2.1.2'
    end
    

    如果是Swift要使用动态库,要加入use_frameworks!这行代码。pod 'ReactiveCocoa'
    纯objc项目 可以是 pod 'ReactiveObjC' 即可

    信号类 RACSignal

    • 获取信号方式

    1. 单元信号

    RACSignal *signal1 = [RACSignal return:@"value"];
    RACSignal *signal2 = [RACSignal error:error];
    RACSignal *signal3 = [RACSignal empty];
    RACSignal *signal4 = [RACSignal never];
    

    2.动态信号

    RACSignal *signal5 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [subscriber sendNext:@1];
        [subscriber sendNext:@2];
        [subscriber sendError:error];
        [subscriber sendCompleted];
        return [RACDisposable disposableWithBlock:^{
            
        }];
    }];
    

    3 Cocoa 桥接

    // 监测对象的该方法是否调用
    RACSignal *signal6 = [view rac_signalForSelector:@selector(setFrame:)];
    // 监测对象是否触发了该事件
    RACSignal *signal7 = [button rac_signalForControlEvents:UIControlEventTouchUpInside];
    // 对象将要释放时发出该信号
    RACSignal *signal8 = [view rac_willDeallocSignal];
    // 监测对象的某个属性是否变化,一旦变化就会发出信号
    RACSignal *signal9 = RACObserve(view, backgroundColor);
    
    

    4.信号转换

    // 对信号每发出一个值进行处理,再返给信号
    RACSignal *signal10 = [signal map:^id(NSString *value) {
        return [value substringFromIndex:1];
    }];
    

    5. 序列转换

    // 集合也能被转换为信号进行操作
    RACSignal *signal11 = collection.rac_sequence.signal;
    
    • 订阅信号

    1. 订阅方法

    // 直接调用 subscribeNext 方法进行订阅
    [signal11 subscribeNext:^(id x) {
        NSLog(@"value %@", x);
    } error:^(NSError *error) {
        NSLog(@"error %@", error);
    } completed:^{
        NSLog(@"finished");
    }];
    

    2.绑定信号

    //属性和信号绑定
    RAC(self.btn,enable) = signal;
    

    3.Cocoa 桥接

    //另个信号都sendNext 后走selector方法
    [self.view rac_liftSelector:@selector(data1:data2:) withSignalsFromArray:@[signal6, signal7]];
    
    • 值转换

    1 Map

    // 把信号A中值map成另一个值
    RACSignal *signalB = [signalA map:^id(NSNumber *value) {
        return @(value.integerValue * 2);
    }];
    

    2 flattenMap 返回一个新的信号

    RACSignal * signalB = [timeSigal flattenMap:^RACStream *(id value) {
                return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
                   
                    [subscriber sendNext:value];
                    [subscriber sendCompleted];
                     return nil;
                }];
            }];
    

    3 MapReplace

    // 把信号A中的值都替换为8
    RACSignal *signalC = [signalA mapReplace:@8];
    // 效果等同于
    RACSignal *signalB = [signalA map:^id(id value) {
        return @8;
    }];
    

    4 ReduceEach

    // reduceEach与map类似,不过只有signalA包含的值是元组类型时才能用它
    // 信号A中包含了N个元组,每个元组内有两个元素,使用 reduceEach 将每个元组中的两个数字取出并相加,返回给信号B
    RACSignal *signalB = [signalA reduceEach:^id(NSNumber *first, NSNumber *second) {
        return @(first.integerValue + second.integerValue);
    }];
    
    • 次数操作

    1 Filter 过滤

    // 过滤掉长度大于2的值
    RACSignal *signalB = [signalA filter:^BOOL(NSString *value) {
        return value.length > 2; //满足需要的条件继续
    }];
    

    2 Ignore

    // 忽略为1的值
    RACSignal *signalC = [signalA ignore:@1];
    // 效果等同于
    RACSignal *signalB = [signalA filter:^BOOL(id value) {
        return ![@1 isEqual:value];
    }];
    // 忽略所有的值
    - (RACSignal *)ignoreValues;
    // 与上次的值不同时才发信号
    - (RACSignal *)distinctUntilChanged;
    // 只会收到一次信号
    RACSubject *subject = [RACSubject subject];
    [[subject distinctUntilChanged] subscribeNext:^(id x) {
        NSLog(@"%@", x);
    }];
    [subject sendNext:@"HMJ"];
    [subject sendNext:@"HMJ"];
    [subject sendNext:@"HMJ"];
    

    3 Take 选择

    // 取A的前两个值
    RACSignal *signalB = [signalA take:2];
    

    4 Take 和 其它

    // 取最后N次的值,会在信号完成后发送
    - (RACSignal *)takeLast:(NSUInteger)count;
    // 一直取值,直到block返回YES,如下例子
    - (RACSignal *)takeUntilBlock:(BOOL (^)(id x))predicate;
    // block返回YES才取值
    - (RACSignal *)takeWhileBlock:(BOOL (^)(id x))predicate;
    // 原理同上
    - (RACSignal *)skipUntilBlock:(BOOL (^)(id x))predicate;
    // 原理同上
    - (RACSignal *)skipWhileBlock:(BOOL (^)(id x))predicate;
    
    [[self.inputTextField.rac_textSignal takeUntilBlock:^BOOL(NSString *value) {
        return [value isEqualToString:@"stop"];
    }] subscribeNext:^(NSString *value) {
        NSLog(@"current value is not `stop`: %@", value);
    }];
    
    // 信号B以 Start 开头
    RACSignal *signalB = [signalA startWith:@"Start"];
    
    // 不停地重复信号A
    RACSignal *signalB = [signalA repeat];
    
    // 如果返回错误则重新订阅,最多2次
    RACSignal *signalB = [signalA retry:2];
    

    5 副作用操作

    RACSignal *signalB = [signalA map:^id(id value) {
        // do some thing
        return value;
    }];
    RACSignal *signalC = [signalA doNext:^(id x) {
        // do some thing
    }];
    
    - (RACSignal *)doError:(void (^)(NSError *error))block;
    - (RACSignal *)doCompleted:(void (^)(void))block;
    - (RACSignal *)initially:(void (^)(void))block;
    - (RACSignal *)finally:(void (^)(void))block;
    

    6 Collet

    // 把信号A的值收集为数组
    RACSignal *signalB = [signalA collect];
    

    7 Aggregate

    // 汇聚,前一次的运算结果为running,下次的信号值为next
    // 如果signalA的值依次为1、2、3、4、5,汇聚之后就是25
    RACSignal *signalB = [signalA aggregateWithStart:@0 reduce:^id(NSNumber *running, NSNumber *next) {
        return @(running.integerValue + next.integerValue);
    }];
    

    8 Scan

    // 使用Aggregate时,如果A不停止,B就永远不会返回值
    // 而使用Scan就不会有这个弊端,每次运算结果都会返回
    RACSignal *signalB = [signalA scanWithStart:@0 reduce:^id(NSNumber *running, NSNumber *next) {
        return @(running.integerValue + next.integerValue);
    }];
    
    • 时间操作

    1 Scheduler

    // 比较准确的时间操作,可代替NSTimer
    - (RACSignal *)interval:(NSTimeInterval)interval
                onScheduler:(RACScheduler *)scheduler;
    - (RACSignal *)interval:(NSTimeInterval)interval
                onScheduler:(RACScheduler *)scheduler
                 withLeeway:(NSTimeInterval)leeway;
    

    2 Delay

    // 准确度比 Scheduler 低
    RACSignal *signalB = [signalA delay:1];
    

    3 Scheduler

    4 Throttle

    // 阀门时间,设置时间内如果没有新的信号才返回值,否则就重新开始计时
    RACSignal *signalB = [signalA throttle:1];
    
    • 组合操作

    1 Concat

    // 按信号顺序合并信号,第一个信号如果不停止,第二个信号就永远无法开始接收
    // 可用于多网络请求时,返回数据需要按顺序拼接的subscriber 发送的值(先是A的值 然后是B的值)
    RACSignal *signalC = [signalA concat:signalB];
    

    2 Merge

    // 将多个信号合并成一个信号,按照发送值的顺序来合并,属于无序合并
    RACSignal *signalC = [signalA merge:signalB];
    RACSignal *signalC = [RACSignal merge:@[signalA, signalB]];
    RACSignal *signalC = [RACSignal merge:RACTuplePack(signalA, signalB)];
    

    3 Zip

    // 合并两个信号的最新值为元组,只有两个信号都有新值时才会合并,signalC发送是一个元祖
    RACSignal *signalC = [signalA zipWith:signalB];
    RACSignal *signalC = [RACSignal zip:@[signalA, signalB]];
    RACSignal *signalC = [RACSignal zip:RACTuplePack(signalA, signalB)];
    

    4 CombineLatest

    加粗

    // 与zip相似,都是合并两个信号的值为元组,不过combineLatest只需一个信号值改变就能合并
    RACSignal *signalC = [signalA combineLatestWith:signalB];
    RACSignal *signalC = [RACSignal combineLatest:@[signalA, signalB]];
    

    5 Sample

    // B触发时才去获取A的实时值
    RACSignal *signalC = [signalA sample:signalB];
    

    6 TakeUntil

    // 获取信号A,B开始就停止
    RACSignal *signalC = [signalA takeUntil:signalB];
    

    7 TakeUntilReplacement

    // 获取信号A,B开始就停止获取A,转而获取B,直到B停止
    RACSignal *signalC = [signalA takeUntilReplacement:signalB];
    
    • 订阅高阶信号
      如果信号中包含了信号,它就是高阶信号。
      下面代码中信号highOrderSignal中包含了信号,所以它是高阶信号。
    RACSignal *signal = @[@1, @2, @3].rac_sequence.signal;
    RACSignal *highOrderSignal = [signal map:^id(id value) {
        return [RACSignal return:value];
    }];
    [highOrderSignal subscribeNext:^(RACSignal *aSignal) {
        [aSignal subscribeNext:^(id x) {
            NSLog(@"%@", x);
        }];
    }];
    

    将信号的值转变成信号叫做信号的升阶,将信号中的信号转变成值叫做信号的降阶

    • 降级操作

    1 .SwitchToLatest

    switchToLatest能够对高阶信号进行降阶,它总是订阅最新的信号。

    RACSignal *signalB = [signalA switchToLatest];
    
    // 如下示例,订阅后最终收到的值为@"1"、@"11"、@"2"。
    // 没有收到@"111"是因为它被发送时,sub1已经不是最新信号了
    // 要注意,最新信号发生error会中断latest信号
    RACSubject *signalOfSignals = [RACSubject subject];
    RACSubject *sub1 = [RACSubject subject];
    RACSubject *sub2 = [RACSubject subject];
    RACSignal *latest = [signalOfSignals switchToLatest];
    [latest subscribeNext:^(id x) {
        NSLog(@"***** %@",x);
    }];
    [signalOfSignals sendNext:sub1];
    [sub1 sendNext:@"1"];
    [sub1 sendNext:@"11"];
    [signalOfSignals sendNext:sub2];
    [sub2 sendNext:@"2"];
    [sub1 sendNext:@"111"];
    

    2 if/then/else

    //如果 signalA 的值为 true 取 signalTrue 的值,否则取 signalFalse 的值。
    RACSignal *signalB = [RACSignal if:signalA
                                  then:signalTrue
                                  else:signalFalse];
    

    3 Flatten

    flatten进行的降阶与switchToLatest不同,它能够获取所有的值。

    RACSignal *signalB = [signalA flatten];
    

    方法- (RACSignal *)flatten:(NSUInteger)maxConcurrent中,maxConcurrent表示最大并发数。比如 flatten:2 表示当前最多只能对信号中的2个信号进行降阶操作,如果有新的信号产生,先进行等待,等到前面有信号结束之后才加入。

    所以 Flatten 类似于 Merge,Flatten:1 类似于 Concat。

    4.FlattenMap

    高阶信号可以用flattenMap进行映射,在block中再对映射出的低阶信号进行映射,最后返回的信号就是降维后的信号。

    • 冷信号 与 热信号
      热信号:
      热信号是主动的,即使你没有订阅事件,它仍然会不断推送。
      热信号可以有多个订阅者,是一对多,信号可以与订阅者共享信息。

    冷信号:
    冷信号是被动的,只有当你订阅的时候,它才会发送消息。
    冷信号只能一对一,当有新的订阅者时,消息会重新完整发送。

    在 RAC 中,RACSubject及其子类是热信号,RACSignal除RACSubject以外的信号是冷信号。

    1.热信号

    RACSubject需要先订阅再发送:

    RACSubject *subject = [RACSubject subject];
    [subject subscribeNext:^(id x) {
        //
    } error:^(NSError *error) {
        //
    } completed:^{
        //
    }];
    
    [subject sendNext:@1];
    [subject sendNext:@2];
    [subject sendNext:@3];
    [subject sendCompleted];
    
    // RACReplaySubject可先发送再订阅:
    //RACReplaySubject是具备快速回播的信号,同时它还能控制“历史值”的数量。
    RACReplaySubject *subject = [RACReplaySubject replaySubjectWithCapacity:1];
    
    [subject sendNext:@1];
    [subject sendNext:@2];
    [subject sendCompleted];
    
    [subject subscribeNext:^(id x) {
        //
    }];
    
    

    相关文章

      网友评论

          本文标题:RAC总结

          本文链接:https://www.haomeiwen.com/subject/dgwzfqtx.html