ReactiveCocoa信号高阶操作

一 升阶和降阶

二 
1.创造高阶信号
(1)RACSignal *signal = [ RACSignal return : @1 ];
RACSignal *signalHighOrder = [ RACSignal return :signal];

(2)RACSignal  *anotherSignal = [signal map :^ id ( id value) {
        return [ RACSignal return :value];
}];

2.订阅高阶信号
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) {
            // get real value here.
}]; }];

三 降阶操作
1.SwitchToLatests
信号1 信号2(将信号1关闭) 信号4 信号5与高阶信号 信号6 信号7 判断信号是否结束



示例一
RACSignal *autoRunButtonClickSignal = [ self .autoRunBtn rac_signalForControlEvents:UIControlEventTouchUpInside];

RACSignal *oneStepButtonClickSignal = [ self .oneStepBtn
rac_signalForControlEvents:UIControlEventTouchUpInside];

RACSignal *idSignal = [ RACSignal return : nil ];
RACSignal *timerSignal = [ RACSignal interval : 1   onScheduler :[ RACScheduler   mainThreadScheduler ]];
autoRunButtonClickSignal = [autoRunButtonClickSignal mapReplace :idSignal];
oneStepButtonClickSignal = [oneStepButtonClickSignal mapReplace :timerSignal];
RACSignal *controlSignal = [autoRunButtonClickSignal merge oneStepButtonClickSignal];
controlSignal = [controlSignal switchToLatest ];

示例二 搜索请求
网络差 连续发送不同的请求 有时后搜索的会先返回 造成搜索不准
RACSignal *searchTextSignal = [ self .searchTextField rac_textSignal];
RACSignal *requestSignals = [searchTextSignal map :^ id ( NSString *searchText) {
        NSString *urlString = [ NSString stringWithFormat :
                               @"http://xxxx.xxx.xxx/?q=%@" , searchText];
        NSURL *url = [ NSURL URLWithString :urlString];
        NSURLRequest *request = [ NSURLRequest requestWithURL :url];
        return [ NSURLConnection rac_sendAsynchronousRequest :request];
    }];  
//第二个信号去请求时会把第一个信号关掉
    requestSignals = [requestSignals switchToLatest ];

2.If/then/else

If/then/ else 本质 & 类似操作

+ ( RACSignal *) if :( RACSignal *)boolSignal
then:( RACSignal *)trueSignal
else :( RACSignal *)falseSignal {
    return [[boolSignal
             map :^( NSNumber *value) {
                 return (value. boolValue ? trueSignal : falseSignal);
             }]
            switchToLatest ];
}

+ ( RACSignal *) switch :( RACSignal *)signal
cases:( NSDictionary *)cases
default :( RACSignal *)defaultSignal;

3.Flatten  不会丢数据 扁平

异步 并发 同时允许2段并发(此时已经满了,黄色和绿色信号)   绿色信号或黄色信号结束了橙色信号才会开始



Flatten: 1 的思考
- 返回 a 信号,b 信号的高阶信号 flatten:1 相当于 a信号concat:b信号
- (RACSignal *)concat;
concat 与1秒延迟信号

RACSignal *signal = @[@1, @3, @7, @9, @8].rac_sequence.signal;
RACSignal *timerSignal = [[signal map:^id(id value) {
return [[RACSignal return:value] delay:1];
}] concat];

降阶操作总结
SwitchToLatests (将上一个信号抛弃)
Flatten (Merge)
Concat (Flatten:1)

四 思考

1.改变某个值的个数 
返回的是1,2,2,3,3,3
RACSignal *signal = @[@1, @2, @3].rac_sequence.signal;
RACSignal *mappedSignal = [[signal map:^id(NSNumber *value) {
return [[[RACSignal return:value] repeat]             take:value.integerValue]; 
}] flatten];

2.将一个值改为一个错误
  RACSignal *signal = @[@1 , @2 , @3 , @0] . rac_sequence . signal ;
    RACSignal *mappedSignal = [[signal map:^ id (NSNumber *value) {   if (value.integerValue == 0 ) {
            return [RACSignal error:[NSError errorWithDomain: @"0" code: 0   } else {
return [RACSignal return :value];
}
}] flatten];

3.改变值的时间间隔
RACSignal  *signal =  @[ @"♪5" , @"♬1" , @"♬2" , @"♬3" , @"♩4" ]
    . rac_sequence
    . signal ;
NSDictionary *toneLengthMap = @{ @"♩" : @0.5 ,
                                    @"♪" : @0.25 ,
                                    @"♬" : @0.125} ;

RACSignal *mappedSignal = [[signal map :^ id ( NSString *value) {
        NSString *tone = [value substringFromIndex : 1 ];
        NSString *length = [value substringToIndex : 1 ];
        NSNumber *toneValue = @( tone. integerValue ) ;
        NSNumber *toneLength = toneLengthMap[length];
        return [[ RACSignal return :toneValue]
                concat :[[ RACSignal empty ]
                        delay : toneLength. doubleValue ]];
        }] concat ];
delay 是不靠谱的(concat一个 empty 信号,delay 延长)

4.Map ————>Flatten  FlattenMap 高阶 >降阶

五  FlattenMap
1.重要性
可以用 FlattenMap 实现很多的信号转换
支持串行异步操作(类似 Promise)
满足 Monad 部分定义 (bind 和 return 才完全满足)

FlattenMap要求传入信号,然后返回扁平化后的 value
RACSignal *flatten = [signal flattenMap:^RACStream *(RACSignal *value) {
        return value;
    }];
RACSignal *map = [signal flattenMap:^RACStream *( id value) {
        id anotherValue = value; // map here!
        return [RACSignal return : anotherValue];
    }];
过滤掉空的值
RACSignal *filter = [signal flattenMap:^RACStream *( id value) {
        BOOL filter = (value == nil ); // filter here!
        return filter ? [RACSignal empty] : [RACSignal return :value];
    }];


在实际使用时的重要场景
RACSignal *signal = [ RACSignal return : @" http://xx.com/a " ];
RACSignal *getSignal = [signal flattenMap : ^ RACStream *( NSString *url) {
        NSURLRequest *request = [ NSURLRequest requestWithURL :[ NSURL URLWithString :url]];
        return [ NSURLConnection rac_sendAsynchronousRequest :request];
    }];
RACSignal *jsonSignal = [getSignal flattenMap : ^ RACStream *( NSData *data) {
        NSError *error = nil ;
        id result = [ NSJSONSerialization JSONObjectWithData :data options : 0 error :&error];
        return error ==  nil ? [ RACSignal return :result]: [ RACSignal error : error];
    }];
RACSignal *getItemSignal = [jsonSignal flattenMap : ^ RACStream *( NSDictionary *value) {
        if (![value isKindOfClass :[ NSDictionary class ]] || value[ @"data.url" ] == nil ) {
            return [RACSignal error:someError];
        }
        NSURLRequest *anotherRequest = [ NSURLRequest requestWithURL : [ NSURL URLWithString :value[ @"data.url" ]]];
        return [ NSURLConnection rac_sendAsynchronousRequest :anotherRequest];
    }];


2.FlattenMap 与 monad,bind
  • Functor,Applicative,Monad 概念
  • FlattenMap 符合 Monad 的 bind 定义,但是无法实现 takeUntil:操作,无法做副作用操作例如 take:的计数
   
  - ( instancetype )flattenMap:(RACStream * (^)( id value))block;
 - ( instancetype )bind:(RACStreamBindBlock (^)( void ))block;
    typedef RACStream * (^RACStreamBindBlock)( id value, BOOL *stop);

3.bind妙用
- ( RACSignal *)take:( NSUInteger )count {
    if (count == 0 ) return [ RACSignal empty ];
    return [ self bind:^{
        __block NSUInteger taken = 0 ;
        return ^ id ( id value, BOOL *stop) {
            if (taken < count) {
                ++taken;
                if (taken == count) *stop = YES ;
                return [class return :value];
            } else {
                return nil ; }
        }; }];
}

4.bind简单实现和问题
- ( RACSignal *)bind:( RACStreamBindBlock (^)( void ))block;
{
    return [ RACSignal createSignal :^ RACDisposable *( id < RACSubscriber > subscriber) {
        RACStreamBindBlock bindBlock = block();
        [ self subscribeNext:^( id x) {
            BOOL stop = NO ;
            RACSignal *signal = (RACSignal *)bindBlock(x, &stop);
            if (signal == nil || stop) { [subscriber sendCompleted];
            } else {
                [signal subscribeNext:^( id x) { [subscriber sendNext:x];
                } error:^(NSError *error) { [subscriber sendError:error];
                } completed:^{ }];
            }
        } error:^(NSError *error) { [subscriber sendError:error];
        } completed:^{ [subscriber sendCompleted]; }];
        return nil ;
    }]; }


六 有用的高阶操作
- (RACSignal *)try:( BOOL (^)( id value, NSError **errorPtr))tryBlock;  对每个值进行分析,用来简化 flattenMap 等操作
- ( RACSignal *)tryMap:( id (^)( id value, NSError **errorPtr))mapBlock;
- (RACSignal *)catch:(RACSignal * (^)(NSError *error))catchBlock;
- ( RACSignal *)catchTo:( RACSignal *)signal;
- (RACSignal *)timeout:( NSTimeInterval )interval
           onScheduler:(RACScheduler *)scheduler;


七 扩展问题
不能 信号是 pushDriver 只能被动接收 浓缩信号变短(冷热信号操作)
































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值