美文网首页
ReactiveCocoa常用方法总结

ReactiveCocoa常用方法总结

作者: 劉光軍_MVP | 来源:发表于2018-12-04 18:52 被阅读124次

    1、RACSignal使用:

    // RACSignal使用步骤:
        // 1.创建信号 + (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe
        // 2.订阅信号,才会激活信号. - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock
        // 3.发送信号 - (void)sendNext:(id)value
        
        
        // RACSignal底层实现:
        // 1.创建信号,首先把didSubscribe保存到信号中,还不会触发。
        // 2.当信号被订阅,也就是调用signal的subscribeNext:nextBlock
        // 2.2 subscribeNext内部会创建订阅者subscriber,并且把nextBlock保存到subscriber中。
        // 2.1 subscribeNext内部会调用siganl的didSubscribe
        // 3.siganl的didSubscribe中调用[subscriber sendNext:@1];
        // 3.1 sendNext底层其实就是执行subscriber的nextBlock
        
        // 1.创建信号
        RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            
            // block调用时刻:每当有订阅者订阅信号,就会调用block。
            
            // 2.发送信号
            [subscriber sendNext:@1];
            
            // 如果不在发送数据,最好发送信号完成,内部会自动调用[RACDisposable disposable]取消订阅信号。
            [subscriber sendCompleted];
     
            return [RACDisposable disposableWithBlock:^{
                
                // block调用时刻:当信号发送完成或者发送错误,就会自动执行这个block,取消订阅信号。
                
                // 执行完Block后,当前信号就不在被订阅了。
                
                NSLog(@"信号被销毁");
                
            }];
        }];
        
        // 3.订阅信号,才会激活信号.
        [siganl subscribeNext:^(id x) {
            // block调用时刻:每当有信号发出数据,就会调用block.
            NSLog(@"接收到数据:%@",x);
        }];
    
    

    2、RACSubject当做代理使用

    步骤一:在第二个控制器.h,添加一个RACSubject代替代理。
    @interface TwoViewController : UIViewController
    
    @property (nonatomic, strong) RACSubject *delegateSignal;
    
    @end
    
    步骤二:监听第二个控制器按钮点击
    @implementation TwoViewController
    - (IBAction)notice:(id)sender {
        // 通知第一个控制器,告诉它,按钮被点了
        
         // 通知代理
         // 判断代理信号是否有值
        if (self.delegateSignal) {
            // 有值,才需要通知
            [self.delegateSignal sendNext:nil];
        }
    }
    @end
    
    步骤三:在第一个控制器中,监听跳转按钮,给第二个控制器的代理信号赋值,并且监听.
    @implementation OneViewController 
    - (IBAction)btnClick:(id)sender {
        
        // 创建第二个控制器
        TwoViewController *twoVc = [[TwoViewController alloc] init];
        
        // 设置代理信号
        twoVc.delegateSignal = [RACSubject subject];
        
        // 订阅代理信号
        [twoVc.delegateSignal subscribeNext:^(id x) {
           
            NSLog(@"点击了通知按钮");
        }];
        
        // 跳转到第二个控制器
        [self presentViewController:twoVc animated:YES completion:nil];
        
    }
    @end
    

    3、RACSequence和RACTuple结合使用遍历字典和数组

    // 1.遍历数组
        NSArray *numbers = @[@1,@2,@3,@4];
    // 这里其实是三步
        // 第一步: 把数组转换成集合RACSequence numbers.rac_sequence
        // 第二步: 把集合RACSequence转换RACSignal信号类,numbers.rac_sequence.signal
        // 第三步: 订阅信号,激活信号,会自动把集合中的所有值,遍历出来。
        [numbers.rac_sequence.signal subscribeNext:^(id x) {
           
            NSLog(@"%@",x);
        }];
    
    // 2.遍历字典,遍历出来的键值对会包装成RACTuple(元组对象)
        NSDictionary *dict = @{@"name":@"xmg",@"age":@18};
        [dict.rac_sequence.signal subscribeNext:^(RACTuple *x) {
           
            // 解包元组,会把元组的值,按顺序给参数里面的变量赋值
            RACTupleUnpack(NSString *key,NSString *value) = x;
            
            // 相当于以下写法
    //        NSString *key = x[0];
    //        NSString *value = x[1];
            
            NSLog(@"%@ %@",key,value);
            
        }];
    
    // 3.字典转模型
        // 3.1 OC写法
        NSString *filePath = [[NSBundle mainBundle] pathForResource:@"test.plist" ofType:nil];
        
        NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];
        
        NSMutableArray *items = [NSMutableArray array];
        
        for (NSDictionary *dict in dictArr) {
            TestModel *item = [TestModel yy_modelWithDictionary:dict];
            [items addObject:item];
        }
    // 3.2 RAC写法
        NSString *filePath = [[NSBundle mainBundle] pathForResource:@"test.plist" ofType:nil];
        
        NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];
    
        NSMutableArray *flags = [NSMutableArray array];
        
        
        // rac_sequence注意点:调用subscribeNext,并不会马上执行nextBlock,而是会等一会。
        [dictArr.rac_sequence.signal subscribeNext:^(id x) {
            // 运用RAC遍历字典,x:字典
            
            TestModel *item = [TestModel yy_modelWithDictionary:dict];
            
            [flags addObject:item];
            
        }];
    
       // 3.3 RAC高级写法:
        NSString *filePath = [[NSBundle mainBundle] pathForResource:@"test.plist" ofType:nil];
        
        NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];
        // map:映射的意思,目的:把原始值value映射成一个新值
        // array: 把集合转换成数组
        // 底层实现:当信号被订阅,会遍历集合中的原始值,映射成新值,并且保存到新的数组里。
        NSArray *flags = [[dictArr.rac_sequence map:^id(id value) {
         
            return [TestModel yy_modelWithDictionary: value];
            
        }] array];
    
    
    

    4、RACCommand

    // 一、RACCommand使用步骤:
        // 1.创建命令 initWithSignalBlock:(RACSignal * (^)(id input))signalBlock
        // 2.在signalBlock中,创建RACSignal,并且作为signalBlock的返回值
        // 3.执行命令 - (RACSignal *)execute:(id)input
        
        // 二、RACCommand使用注意:
        // 1.signalBlock必须要返回一个信号,不能传nil.
        // 2.如果不想要传递信号,直接创建空的信号[RACSignal empty];
        // 3.RACCommand中信号如果数据传递完,必须调用[subscriber sendCompleted],这时命令才会执行完毕,否则永远处于执行中。
        // 4.RACCommand需要被强引用,否则接收不到RACCommand中的信号,因此RACCommand中的信号是延迟发送的。
        
        // 三、RACCommand设计思想:内部signalBlock为什么要返回一个信号,这个信号有什么用。
        // 1.在RAC开发中,通常会把网络请求封装到RACCommand,直接执行某个RACCommand就能发送请求。
        // 2.当RACCommand内部请求到数据的时候,需要把请求的数据传递给外界,这时候就需要通过signalBlock返回的信号传递了。
        
        // 四、如何拿到RACCommand中返回信号发出的数据。
        // 1.RACCommand有个执行信号源executionSignals,这个是signal of signals(信号的信号),意思是信号发出的数据是信号,不是普通的类型。
        // 2.订阅executionSignals就能拿到RACCommand中返回的信号,然后订阅signalBlock返回的信号,就能获取发出的值。
        
        // 五、监听当前命令是否正在执行executing
        
        // 六、使用场景,监听按钮点击,网络请求
    
    
        // 1.创建命令
        RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
            
            
            NSLog(@"执行命令");
            
            // 创建空信号,必须返回信号
            //        return [RACSignal empty];
            
            // 2.创建信号,用来传递数据
            return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
                
                [subscriber sendNext:@"请求数据"];
                
                // 注意:数据传递完,最好调用sendCompleted,这时命令才执行完毕。
                [subscriber sendCompleted];
                
                return nil;
            }];
            
        }];
        
        // 强引用命令,不要被销毁,否则接收不到数据
        _conmmand = command;
        
        
       
        // 3.订阅RACCommand中的信号
        [command.executionSignals subscribeNext:^(id x) {
            
            [x subscribeNext:^(id x) {
                
                NSLog(@"%@",x);
            }];
            
        }];
        
        // RAC高级用法
        // switchToLatest:用于signal of signals,获取signal of signals发出的最新信号,也就是可以直接拿到RACCommand中的信号
        [command.executionSignals.switchToLatest subscribeNext:^(id x) {
            
            NSLog(@"%@",x);
        }];
        
        // 4.监听命令是否执行完毕,默认会来一次,可以直接跳过,skip表示跳过第一次信号。
        [[command.executing skip:1] subscribeNext:^(id x) {
            
            if ([x boolValue] == YES) {
                // 正在执行
                NSLog(@"正在执行");
                
            }else{
                // 执行完成
                NSLog(@"执行完成");
            }
            
        }];
       // 5.执行命令
        [self.conmmand execute:@1];
    

    5、其余常见用法

    1 代替代理:
    
    //rac_signalForSelector:用于替代代理。(没有想明白)
    
    2 代替KVO :
    
    rac_valuesAndChangesForKeyPath:用于监听某个对象的属性改变。
    
    // 把监听redV的center属性改变转换成信号,只要值改变就会发送信号
        // observer:可以传入nil
        [[redV rac_valuesAndChangesForKeyPath:@"center" options:NSKeyValueObservingOptionNew observer:nil] subscribeNext:^(id x) {
    
            NSLog(@"%@",x);
    
        }];
    
    
    3 监听事件:
    
    rac_signalForControlEvents:用于监听某个事件。
    // 把按钮点击事件转换为信号,点击按钮,就会发送信号
    
        [[self.btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
    
            NSLog(@"按钮被点击了");
        }];
    
    4 代替通知:
    
    rac_addObserverForName:用于监听某个通知。
    
    [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(id x) {
            NSLog(@"键盘弹出");
        }];
    
    
    5 监听文本框文字改变:
    
    rac_textSignal:只要文本框发出改变就会发出这个信号。
    
    [_textField.rac_textSignal subscribeNext:^(id x) {
    
           NSLog(@"文字改变了%@",x);
       }];
    
    

    6、常见宏

    1、RAC(TARGET, [KEYPATH, [NIL_VALUE]]):用于给某个对象的某个属性绑定。
    // 只要文本框文字改变,就会修改label的文字
        RAC(self.labelView,text) = _textField.rac_textSignal;
    
    2、RACObserve(self, name):监听某个对象的某个属性,返回的是信号。
    
    [RACObserve(self.view, center) subscribeNext:^(id x) {
          
            NSLog(@"%@",x);
        }];
    
    3、RACTuplePack:把数据包装成RACTuple(元组类)
    
    // 把参数中的数据包装成元组
        RACTuple *tuple = RACTuplePack(@10,@20);
    
    4、RACTupleUnpack:把RACTuple(元组类)解包成对应的数据。
        // 把参数中的数据包装成元组
        RACTuple *tuple = RACTuplePack(@"xmg",@20);
        
        // 解包元组,会把元组的值,按顺序给参数里面的变量赋值
        // name = @"xmg" age = @20
        RACTupleUnpack(NSString *name,NSNumber *age) = tuple;
    
    
    

    相关文章

      网友评论

          本文标题:ReactiveCocoa常用方法总结

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