美文网首页专注iOS开发iOSReactiveCocoa相关
###iOS开发之ReactiveCocoa(进阶)

###iOS开发之ReactiveCocoa(进阶)

作者: 纳萨立克 | 来源:发表于2016-03-30 17:16 被阅读1335次

    iOS开发之ReactiveCocoa(进阶)

    Map : 映射

     UITextField *textField =[[UITextField alloc]initWithFrame:CGRectMake(100, 100, 100, 40)];
     textField.backgroundColor =[UIColor redColor];
     [self.view addSubview:textField];
     
     [[textField.rac_textSignal map:^id(NSString * value) {
            
            return @(value.length);
            
      }] subscribeNext:^(NSNumber * x) {
            
            NSLog(@"%@",x);
       }];
     
    

    输入Ricky:

    结果:

    结果

    filter: 过滤

    
    //只有当text.length>3的时候才会订阅改消息
        [[textField.rac_textSignal filter:^BOOL(NSString * text) {
           
            return text.length>3;
            
        }] subscribeNext:^(id x) {
           
            NSLog(@"%@",x);
            
        }];
    

    同样输入Ricky结果就是:


    delay:延时

    
    //延时2秒发送消息
    
           RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        
                [subscriber sendNext:@"Ricky"];
                [subscriber sendCompleted];
        
                return nil;
        
            }] delay:2];
        
        
            [signal subscribeNext:^(id x) {
        
                NSLog(@"%@",x);
            }];
    

    startWith:在发送消息之前,先发送一个消息

            RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        
                [subscriber sendNext:@"Ricky"];
                [subscriber sendCompleted];
        
                return nil;
        
            }] startWith:@"RAC"];
        
        
            [signal subscribeNext:^(id x) {
        
                NSLog(@"%@",x);
            }];
        
    

    timeout :超时

    
    //设置超时时间为2秒,当超过2秒还没有发送消息的时候,就不会发送了
            RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        
                [[RACScheduler mainThreadScheduler] afterDelay:3 schedule:^{
        
                    [subscriber sendNext:@"Ricky"];
                    [subscriber sendCompleted];
                }];
        
                return nil;
        
            }] timeout:2 onScheduler:[RACScheduler mainThreadScheduler]];
        
        
            [signal subscribeNext:^(id x) {
        
                NSLog(@"%@",x);
            }];
        
        
    
    

    take :发送多个消息的时候,取最前面的几条

                RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        
                    [subscriber sendNext:@"Ricky1"];
                    [subscriber sendNext:@"Ricky2"];
                    [subscriber sendNext:@"Ricky3"];
                    [subscriber sendNext:@"Ricky4"];
                    [subscriber sendCompleted];
        
                    return nil;
        
                }] take:2];
        
        
                [signal subscribeNext:^(id x) {
        
                    NSLog(@"%@",x);
                }];
    

    takelast :发送多个消息的时候,取最后面的几条

                RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        
                    [subscriber sendNext:@"Ricky1"];
                    [subscriber sendNext:@"Ricky2"];
                    [subscriber sendNext:@"Ricky3"];
                    [subscriber sendNext:@"Ricky4"];
                    [subscriber sendCompleted];
        
                    return nil;
        
                }] takeLast:3];
        
        
                [signal subscribeNext:^(id x) {
        
                    NSLog(@"%@",x);
                }];
    

    takeUntil: RACSignal (发送在takeUntil后面的信号完成前的消息)

    
    // RAC这个消息是2秒后完成,所以Ricky1 Ricky2这两个消息是可以发送到 而3秒后的Ricky3 Ricky4就不会发送.
                RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        
                    [subscriber sendNext:@"Ricky1"];
                    [subscriber sendNext:@"Ricky2"];
                    
                    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                        
                        [subscriber sendNext:@"Ricky3"];
                        [subscriber sendNext:@"Ricky4"];
                         [subscriber sendCompleted];
                    });
    
                    [subscriber sendCompleted];
        
                    return nil;
        
                }] takeUntil:[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
                    
                    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                        
                        [subscriber sendNext:@"RAC"];
                        [subscriber sendCompleted];
                    });
                    
    
                    return nil;
                    
                }]];
        
        
                [signal subscribeNext:^(id x) {
        
                    NSLog(@"%@",x);
                }];
    

    takeWhileBlock :当takeWhileBlock返回YES的时候发送消息

                RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        
                    [subscriber sendNext:@"Ricky1"];
                    [subscriber sendNext:@"Ricky2"];
                    [subscriber sendNext:@"Ricky3"];
                    [subscriber sendNext:@"Ricky4"];
                    [subscriber sendCompleted];
                    
        
                    return nil;
        
                }] takeWhileBlock:^BOOL(id x) {
                    
                    return YES;
                    
                }];
        
                [signal subscribeNext:^(id x) {
        
                    NSLog(@"%@",x);
                }];
    

    skip: 跳过

    //跳过前2次
        RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            
            [subscriber sendNext:@"Ricky1"];
            [subscriber sendNext:@"Ricky2"];
            [subscriber sendNext:@"Ricky3"];
            [subscriber sendNext:@"Ricky4"];
            [subscriber sendCompleted];
            
            return nil;
            
        }] skip:2];
        
        
        [signal subscribeNext:^(id x) {
            
            NSLog(@"%@",x);
        }];
    
    

    skipWhileBlcok 和 skipUntilBlcok

    • skipWhileBlcok:当Block返回YES的时候跳过,返回No的时候发送.
    • skipUntilBlcok: skipUntilBlcok和skipWhileBlcok相反,当Block返回NO的时候跳过,返回YES的时候发送.

    结合及时搜索优化

    当我们在做及时搜索的时候,例如在UITextField中输入搜索内容,每当我们输入一个字符的时候当会请求服务器,无形中给服务器带来了很大的压力

        UITextField *textField =[[UITextField alloc]initWithFrame:CGRectMake(100, 100, 100, 40)];
        textField.backgroundColor =[UIColor redColor];
        
        [self.view addSubview:textField];
        
        
        [textField.rac_textSignal subscribeNext:^(NSString * text) {
           
            NSLog(@"request--- %@",text);
        }];
    
    • 优化请求时间间隔:throttle(节流)

    throttle:设置一个间隔时间,当两次信号之间的时间差下于这个时间就不会发送请求

        [[textField.rac_textSignal throttle:0.3] subscribeNext:^(NSString * text) {
           
            NSLog(@"request--- %@",text);
        }];
    
    • distinctUntilChanged: 优化请求字符一样的时候(当后一个请求和前一个请求一样的时候,就可以不用请求)
        [[[textField.rac_textSignal throttle:0.3]distinctUntilChanged]
    
         subscribeNext:^(NSString * text) {
           
            NSLog(@"request--- %@",text);
        }];
    
    • ignore :忽略某些 例如上面的空字符
        [[[[textField.rac_textSignal throttle:0.3]distinctUntilChanged] ignore:@"" ]
    
         subscribeNext:^(NSString * text) {
           
            NSLog(@"request--- %@",text);
        }];
    
    
    • switchToLatest :当你请求数据的时候,网络会有延迟,数据还没有返回回来,这时候你发送了新的请求,则我们取消前一次的请求,只发送最新的请求.
        [[[[[[textField.rac_textSignal throttle:0.3]distinctUntilChanged] ignore:@"" ] map:^id(id value) {
          
            return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
               
                [subscriber sendNext:@"Request --- ricky"];
                
                return nil;
            }];
            
        }] switchToLatest]
    
         subscribeNext:^(NSString * text) {
           
            NSLog(@"request--- %@",text);
        }];
    

    多个信号处理

        RACSignal *singalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                
                
                [subscriber sendNext:@"singalA"];
                [subscriber sendCompleted];
            });
            
            return nil;
        }];
        
        
        RACSignal *singalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            
            
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                
                
                [subscriber sendNext:@"singalB"];
                [subscriber sendCompleted];
            });
            
            return nil;
        }];
    
    merge: 同时订阅2个信号
        [[singalA merge:singalB] subscribeNext:^(id x) {
           
            NSLog(@"%@",x);
        }];
    

    singalA延迟2秒,singalB延迟5秒,她们相差了3秒.说明他们是同时发送的

    concat

    singalA完成后 才会订阅singalB 有点像串行队列 A失败了 B就不会被订阅

        [[singalA concat:singalB] subscribeNext:^(id x) {
           
            NSLog(@"%@",x);
        }];
    

    singalA延迟2秒,singalB延迟5秒,她们相差了5秒.说明A发送完,B才发送的.

    zipWith和combineLatest:每个信号都至少要发送一次才可以被订阅.

        [[singalA zipWith:singalB] subscribeNext:^(RACTuple * tuple) {
           
            NSLog(@"%@",tuple);
        }];
        
         [[RACSignal combineLatest:@[singalA,singalB]] subscribeNext:^(RACTuple * tuple) {
           
            NSLog(@"%@",tuple);
    
        }];
        
    

    RAC中的宏(结合例子)

    • UIButton中没有setbackgroundColor forstatus这个方法,使用RAC很简单实现
        UIButton *button =[UIButton buttonWithType:UIButtonTypeCustom];
        
        button.frame = CGRectMake(100, 100, 100, 100);
        button.backgroundColor = [UIColor yellowColor];
        
        [self.view addSubview:button];
        
        
        RAC(button,backgroundColor) = [RACObserve(button, selected) map:^id(NSNumber * selected) {
           
            return [selected boolValue]?[UIColor yellowColor]:[UIColor redColor];
        }];
        
        
        [[button rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(UIButton * x) {
            
            
            x.selected = !x.selected;
            
        }];
        
    
    • RAC快速实现秒表
        UILabel *lab =[[UILabel alloc]initWithFrame:CGRectMake(100, 100, 200, 50)];
        lab.backgroundColor =[UIColor cyanColor];
        
        [self.view addSubview:lab];
        
        
        RAC(lab,text) = [[RACSignal interval:1 onScheduler:[RACScheduler mainThreadScheduler]] map:^id(NSData * value) {
           
            return value.description;
        }];
        
    

    相关文章

      网友评论

      • liyaoyao:你好textField.rac_textSignal用map转换数据,这个map的block会被调用两次,这个能不能设置被调用一次,我试了这个distinctUntilChanged,发现没有作用
      • 倾心cyan:这个真的很强大啊 ~

      本文标题:###iOS开发之ReactiveCocoa(进阶)

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