RAC API使用

RAC的定义

ReactiveCocoa(简称:RAC),其具有函数式编程和响应式编程的特性,是github开源的一套开源框架

RAC的作用

  • 解决开发中状态与状态之间的过多依赖
  • 解决MVC中Controller过于臃肿的问题
  • 提供统一的消息传递机制
  • 使代码高聚合,方便管理

RAC的编程思想

函数响应式编程(FRP)框架、将一切转换为信号


万物皆信号
注意:RAC通过weakify、strongify解决循环引用问题

RAC的API

集合类型的遍历

-(void)rac_sequence {
    NSArray *array = @[@"111",@"222",@"333"];
    //遍历数组
    [array.rac_sequence.signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"rac_array__%@",x);
    }];
    
    NSDictionary *dict = @{@"name":@"lmf",@"age":@"18"};
    [dict.rac_sequence.signal subscribeNext:^(id  _Nullable x) {
        //Tuple:元祖
        //使用方式类似Array
        RACTwoTuple *tuple = x;
        NSLog(@"rac_dict__%@:%@",tuple[0],tuple[1]);
    }];
}

timer

- (void)rac_timer {
    [[RACSignal interval:1 onScheduler: [RACScheduler schedulerWithPriority:(RACSchedulerPriorityHigh) name:@"com.lmf.rac_timer"]] subscribeNext:^(NSDate * _Nullable x) {
        NSLog(@"rac_timer______%@",x);
    }];
}

基础UI&&手势

- (void)rac_ui {
    //button
    [[self.button rac_signalForControlEvents:(UIControlEventTouchUpInside)] subscribeNext:^(__kindof UIControl * _Nullable x) {
        NSLog(@"rac_button1:%@",x);
    }];
    
    self.button.rac_command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id  _Nullable input) {
        NSLog(@"rac_button2:%@",input);
        return [RACSignal empty];
    }];
    
    //textField
    [self.textField.rac_textSignal subscribeNext:^(NSString * _Nullable x) {
        NSLog(@"rac_textField:%@", x);
    }];
    
    //tap
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]init];
    self.label.userInteractionEnabled = YES;
    [self.label addGestureRecognizer:tap];
    [tap.rac_gestureSignal subscribeNext:^(__kindof UIGestureRecognizer * _Nullable x) {
        NSLog(@"rac_tap:%@",x);
    }];
}

通知

- (void)rac_notify {
    [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) {
        NSLog(@"rac_notification:%@", x);
    }];
}

代理

- (void)rac_delegate {
    self.textField.delegate = self;
    [[self rac_signalForSelector:@selector(textFieldDidBeginEditing:) fromProtocol:@protocol(UITextFieldDelegate)] subscribeNext:^(RACTuple * _Nullable x) {
        NSLog(@"rac_delegate:%@",x);
    }];
}

KVO

- (void)rac_kvo {
    [RACObserve(self, name) subscribeNext:^(id  _Nullable x) {
        NSLog(@"rac_kvo:%@",x);
    }];
    self.name = @"lmf";
}

RAC

把一个对象的某个属性绑定一个信号,只要发出信号,就会把信号的内容给对象的属性赋值
- (void)rac_rac {
    RAC(self.label, text) = self.textField.rac_textSignal;
    /*
     //等同于
     [self.textField.rac_textSignal subscribeNext:^(id x) {
     self.label.text = x;
     }];
     */
}

signal

- (void)rac_signal {
    RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id  _Nonnull subscriber) {
        NSLog(@"createSignal");
        [subscriber sendNext:@"发送信号"];
        [subscriber sendError:[NSError errorWithDomain:@"baidu" code:404 userInfo:nil]];
        return [RACDisposable disposableWithBlock:^{
            
            NSLog(@"销毁了");
        }];
    }];
    
    [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"subscribeNext:%@",x);
    }];
    
    [signal subscribeError:^(NSError * _Nullable error) {
        NSLog(@"subscribeError:%@", error);
    }];
}

retry

只要任务失败就会重新执行创建信号中的block的,直到成功
- (void)rac_retry {
    __block int num = 0;
    [[[RACSignal createSignal:^RACDisposable * _Nullable(id  _Nonnull subscriber) {
        if (num == 10) {
            [subscriber sendNext:@10];
        }else {
            num ++;
            [subscriber sendError:[NSError errorWithDomain:@"baidu" code:-1 userInfo:nil]];
        }
        return nil;
    }] retry] subscribeNext:^(id  _Nullable x) {
        NSLog(@"rac_retry_next:%@",x);
    } error:^(NSError * _Nullable error) {
        NSLog(@"rac_retry_error:%@",error);
    }];
    
}

信号超时处理

- (void)rac_timeout {
    RACSignal *signal = [[RACSignal createSignal:^RACDisposable * _Nullable(id  _Nonnull subscriber) {
        return nil;
    }] timeout:1 onScheduler:[RACScheduler currentScheduler]];
    [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"rac_timeout_subscribeNext:%@",x);
    } error:^(NSError * _Nullable error) {
        //超时会执行这段代码
        NSLog(@"rac_timeout_error:%@",error);
    }];
}

switchToLastest

只能用于信号中的信号;获取信号中信号最近发出信号,订阅最近发出的信号
- (void)rac_switchToLastest {
    RACSubject *signalOfSignals = [RACSubject subject];
    RACSubject *signal = [RACSubject subject];
    RACSubject *signal2 = [RACSubject subject];
    [signalOfSignals.switchToLatest subscribeNext:^(id  _Nullable x) {
        NSLog(@"rac_switchToLastest:%@",x);
    }];
    [signalOfSignals sendNext:signal2];
    [signalOfSignals sendNext:signal];
    [signal sendNext:@"hahaha"];
    [signal2 sendNext:@"12345"];
}

takeUntil

当takeUntil传入的信号发出信号或者sendCompleted后,源信号将不再接受信号消息
- (void)rac_takeUntil {
    RACSubject *subject = [RACSubject subject];
    RACSubject *subject2 = [RACSubject subject];
    [[subject takeUntil:subject2] subscribeNext:^(id  _Nullable x) {
        NSLog(@"rac_takeUntil:%@",x);
    }];
    [subject sendNext:@1];
    [subject sendNext:@2];
//    [subject2 sendNext:@3];
    [subject2 sendCompleted];
    [subject sendNext:@4];
    [subject2 sendNext:@5];
    [subject sendNext:@6];
}

take&&takeLast

take和takeLast使用方式一样,take取前x个信号,takeLast取后x个信号,takeLast使用后需要使用sendCompleted,告诉takeLast发送完成
- (void)rac_takeLast {
    RACSubject *subject = [RACSubject subject];
    [[subject takeLast:2] subscribeNext:^(id  _Nullable x) {
        NSLog(@"rac_takeLast:%@",x);
    }];
    
    [subject sendNext:@1];
    [subject sendNext:@2];
    [subject sendNext:@3];
    [subject sendCompleted];
}

skip

跳过前x个信号
- (void)rac_skip {
    [[self.textField.rac_textSignal skip:1] subscribeNext:^(NSString * _Nullable x) {
        NSLog(@"rac_skip:%@",x);
    }];
}

distinctUntilChanged

两次内容不一致就会发出信号,否则被忽略
- (void)rac_distinctUntilChanged {
    RACSubject *subject = [RACSubject subject];
    [[subject distinctUntilChanged] subscribeNext:^(id  _Nullable x) {
        NSLog(@"rac_distinctUntilChanged:%@",x);
    }];
    
    [subject sendNext:@1];
    [subject sendNext:@1];
    [subject sendNext:@2];
    [subject sendNext:@2];
}

ignore

忽略传入的信号
- (void)rac_ignore {
//    [[self.textField.rac_textSignal ignore:@"2"] subscribeNext:^(NSString * _Nullable x) {
//        NSLog(@"rac_ignore:%@",x);
//    }];
    
    RACSubject *subject = [RACSubject subject];
    [[subject ignore:@2] subscribeNext:^(id  _Nullable x) {
        NSLog(@"rac_ignore:%@",x);
    }];
    [subject sendNext:@1];
    [subject sendNext:@2];
    [subject sendNext:@3];
}

filter

在发送信号前,先执行过滤条件,返回true,在发送信号
- (void)rac_filter {
    RACSubject *subject = [RACSubject subject];
    [[subject filter:^BOOL(id  _Nullable value) {
        NSString *str = value;
        return str.length > 6;
    }] subscribeNext:^(id  _Nullable x) {
        NSLog(@"rac_filter:%@",x);
    }];
    [subject sendNext:@"1"];
    [subject sendNext:@"22"];
    [subject sendNext:@"666666"];
    [subject sendNext:@"7777777"];
}

reduce

信号组合后,每次有信号发出,先执行block进行组合,再发送信号
reduce block注意事项:
参数:有多少信号组合,block就有多少个参数,每个参数就是之前信号发出的内容
返回值:组合后的内容
- (void)rac_reduce {
    
    RACSignal *signal1 = self.textField.rac_textSignal;
    RACSignal *signal2 = [self.button rac_signalForControlEvents:(UIControlEventTouchUpInside)];
    RACSignal *reduceSignal = [RACSignal combineLatest:@[signal1, signal2] reduce:^(id value1, id value2){
        return [NSString stringWithFormat:@"组合reduce == 1:%@ 2:%@", value1, value2];
    }];
    [reduceSignal subscribeNext:^(id  _Nullable x) {
        NSLog(@"rac_reduce:%@",x);
    }];
}

combineLatestWith

当组合信号被订阅,内部会自动订阅多个信号,必须多个信号都被触发才会触发合并信号,并会把多个信号的值组合成元祖返回
- (void)rac_combineLast {
    RACSignal *signal1 = self.textField.rac_textSignal;
    RACSignal *signal2 = [self.button rac_signalForControlEvents:(UIControlEventTouchUpInside)];
    
    RACSignal *comSignal = [signal1 combineLatestWith:signal2];
    [comSignal subscribeNext:^(id  _Nullable x) {
        NSLog(@"rac_combineLast:%@",x);
    }];
}

zip(不太明白)

每当signalA或者signalB发出信号,就会判断signalA,signalB有没有发出个信号,有就会把最近发出的信号都包装成元组发出
- (void)rac_zip {
    RACSignal *signal1 = self.textField.rac_textSignal;
    RACSignal *signal2 = [self.button rac_signalForControlEvents:(UIControlEventTouchUpInside)];
    RACSignal *zipSignal = [signal1 zipWith:signal2];
    [zipSignal subscribeNext:^(id  _Nullable x) {
        NSLog(@"rac_zip:%@",x);
    }];
}

merge

把多个信号合并成一个信号,任何一个信号发送数据,都可以监听到
- (void)rac_merge {
    RACSignal *signal1 = self.textField.rac_textSignal;
    RACSignal *signal2 = [self.button rac_signalForControlEvents:(UIControlEventTouchUpInside)];
    
    RACSignal *mergeSignal = [signal1 merge:signal2];
    [mergeSignal subscribeNext:^(id  _Nullable x) {
        NSLog(@"rac_merge:%@",x);
    }];
}

then

第一个信号必须执行sendCompleted 第二个信号才会触发,监听的是第二个信号的值
- (void)rac_then {
    [[[RACSignal createSignal:^RACDisposable * _Nullable(id  _Nonnull subscriber) {
//        [subscriber sendNext:@(123)];
        [subscriber sendCompleted];
        return nil;
    }] then:^RACSignal * _Nonnull{
        return [RACSignal createSignal:^RACDisposable * _Nullable(id  _Nonnull subscriber) {
            [subscriber sendNext:@(456)];
            [subscriber sendCompleted];
            return nil;
        }];
    }] subscribeNext:^(id  _Nullable x) {
        NSLog(@"rac_then:%@",x);
    }];
}

contact

先监听前一个信号,再监听后面的信号
- (void)rac_contact {
    RACSignal *signal1 = [RACSignal createSignal:^RACDisposable * _Nullable(id  _Nonnull subscriber) {
        [subscriber sendNext:@(123)];
        [subscriber sendCompleted];
        return nil;
    }];
    RACSignal *signal2 = [RACSignal createSignal:^RACDisposable * _Nullable(id  _Nonnull subscriber) {
        [subscriber sendNext:@(456)];
        [subscriber sendCompleted];
        return nil;
    }];
    RACSignal *contactSignal = [signal1 concat:signal2];
    [contactSignal subscribeNext:^(id  _Nullable x) {
        NSLog(@"rac_contact:%@",x);
    }];
}

bind

需要单独导入RACReturnSignal.h
- (void)rac_bind {
    [[self.textField.rac_textSignal bind:^RACSignalBindBlock _Nonnull{
        return ^RACSignal *(id value, BOOL *sotp) {
            return [RACReturnSignal return:[NSString stringWithFormat:@"输出结果%@", value]];
        };
    }] subscribeNext:^(id  _Nullable x) {
        NSLog(@"rac_bind:%@",x);
    }];
}

map

将源信息做了处理
- (void)rac_map {
    [[self.textField.rac_textSignal map:^id _Nullable(NSString * _Nullable value) {
        return [NSString stringWithFormat:@"nb_%@",value];
    }] subscribeNext:^(id  _Nullable x) {
        NSLog(@"rac_map:%@",x);
    }];
}

flattenMap

作用好像和map类似 都是对源信号进行了转换
- (void)rac_flattenMap {
    [[self.textField.rac_textSignal flattenMap:^__kindof RACSignal * _Nullable(NSString * _Nullable value) {
        return [RACReturnSignal return:[NSString stringWithFormat:@"输出结果:%@",value]];
    }] subscribeNext:^(id  _Nullable x) {
        NSLog(@"rac_flattenMap:%@",x);
    }];
}

RACMulticastConnection

当有多个订阅者时,按传统写法会发送多次信号,这时我们可以通过RACMulticatConnection,来解决
- (void) rac_multicastConnection {
    /*
     // 普通写法, 这样的缺点是:每订阅一次信号就得重新创建并发送请求
     RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {
     // 发送信号
     [subscriber sendNext:@"我是信号"];
     return nil;
     }];
     [signal subscribeNext:^(id x) {
     NSLog(@"%@", x);
     }];
     [signal subscribeNext:^(id x) {
     NSLog(@"%@", x);
     }];
     [signal subscribeNext:^(id x) {
     NSLog(@"%@", x);
     }];
     */
    // 比较好的做法:使用RACMulticastConnection,无论订阅多少次,只发送一次
    RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {
        // 发送信号
        [subscriber sendNext:@"我是信号"];
        return nil;
    }];
    RACMulticastConnection *connection = [signal publish];
    [connection.signal subscribeNext:^(id x) {
        NSLog(@"1:%@", x);
    }];
    [connection.signal subscribeNext:^(id x) {
        NSLog(@"2:%@", x);
    }];
    [connection.signal subscribeNext:^(id x) {
        NSLog(@"3:%@", x);
    }];
    //进行连接
    [connection connect];
}

RACCommand

RAC中用于处理事件的类,可以把事件如何处理,事件中的数据如何传递,包装到这个类中,他可以很方便的监控事件的执行过程
- (void) rac_command {
    //创建命令
    RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id  _Nullable input) {
        NSLog(@"%@", input);
        return [RACSignal createSignal:^RACDisposable * _Nullable(id  _Nonnull subscriber) {
            [subscriber sendNext:@"额 我是谁"];
            //¥¥¥处使用
            [subscriber sendCompleted];
            return nil;
        }];
    }];
    
    /*
     //方式一:先获取执行命令返回的信号再订阅
     RACSignal *singnal = [command execute:@111];
     [singnal subscribeNext:^(id  _Nullable x) {
     NSLog(@"这是什么:%@",x);
     }];
     */

    /*
     //方式二:要先订阅再执行命令
     [command.executionSignals subscribeNext:^(id  _Nullable x) {
     [x subscribeNext:^(id  _Nullable x) {
     NSLog(@"这是啥:%@",x);
     }];
     }];

     [command execute:@222];
     */

    /*
     //方式三:要先订阅再执行命令,订阅方式有差异
     [command.executionSignals.switchToLatest subscribeNext:^(id  _Nullable x) {
     NSLog(@"这是啥:%@",x);
     }];
     [command execute:@333];
     */
    
    //¥¥¥
    [command.executing subscribeNext:^(NSNumber * _Nullable x) {
        if ([x boolValue] == YES) {
            NSLog(@"正在执行:%@", x);
        }
        else {
            NSLog(@"执行完成或者没有执行");
        }
    }];
    [command execute:@444];
}

生活如此美好,今天就点到为止。。。

你可能感兴趣的:(RAC API使用)