美文网首页
ReactiveCocoa之基本使用

ReactiveCocoa之基本使用

作者: 殇鑫 | 来源:发表于2018-05-16 15:01 被阅读0次

    之前写了一篇关于ReactiveCocoa入门的文章,里面只是简单的介绍了ReactiveCocoa 的基本方法。接下来我会针对不同的方法 怎么使用做一下简单的介绍。

    Tips:

    cocoPods导入时 oc : pod ‘ReactiveObjC’ swift : pod ‘ReactiveCocoa’ 详细可查看官方介绍 http://reactivecocoa.io

    话不多说上代码

    RACSignal(信号类)

    1、RAC 的核心就是RACSignal 它是一个信号类 一般需要三个步骤。

    1.1 创建信号
    1.2 订阅信号
    1.3 发送信号

     //创建信号
        RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
            /**
             RACSubscriber 是一个协议类 只有遵循这个协议才能成为订阅者
             */
            //发送信号 可以是任意类型
             [subscriber sendNext:self.dataArray];
            //信号发送成功
            [subscriber sendCompleted];
            
            return [RACDisposable disposableWithBlock:^{
            //销毁信号
                
            }];
            
        }];
        
        //订阅信号
        [signal subscribeNext:^(id  _Nullable x) {
            
            NSLog(@"接受数据---%@",x);
            
        }];
    

    你可以这样理解 你在某宝上相中了一款商品需要预付定金 等开售的时候开始给你发货。预付定金相当于订阅信号、开售发货相当于发送信号。是不是这个道理。

    2、底层原理简单分析

    2.1 创建信号,首先把didSubscribe保存到信号中,还不会触发。
    2.2 当信号被订阅,也就是调用signal的subscribeNext:nextBlock
    2.3 subscribeNext内部会创建订阅者subscriber,并且把nextBlock保存到subscriber中。
    2.4 subscribeNext内部会调用siganl的didSubscribe
    2.5 signal的didSubscribe中调用[subscriber sendNext:id];
    2.6 sendNext底层其实就是执行subscriber的nextBlock
    点击这里可以查看RACSignal的常用用法

    RACSubject

    RACSubject:信号提供者,自己可以充当信号,又能发送信号。

     RACSubject *subject = [RACSubject subject];
      [subject subscribeNext:^(id  _Nullable x) {
            
       //订阅信号
            
        }];
         //发送信号
        [subject sendNext:@"要发送的数据"];
    
    - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
        NSCParameterAssert(nextBlock != NULL);
        
        RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
        return [self subscribe:o];
    }
    

    RACSubscriber:表示订阅者的意思,用于发送信号,这是一个协议,不是一个类,只要遵守这个协议,并且实现方法才能成为订阅者。通过create创建的信号,都有一个订阅者,帮助他发送数据。

    代替代理

    利用RACSubject替换代理
    SecondViewController.h 中 声明一个RACSubject代理

    @property (nonatomic,strong)RACSubject *delegateSignal;
    

    SecondViewController.m 中 创建一个事件传递数据

     [[self.sendButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
    
            if (self.delegateSignal) {
                //发送信号
                [self.delegateSignal sendNext:@"代理需要传的数据"];
            }
            
        }];
    

    跳转SecondViewController时接受代理

     [[self.signalButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
            
            NSLog(@"button点击事件 ---%@",x);
            SecondViewController *second = [[SecondViewController alloc] init];
            second.title = @"second";
            //设置代理信号----创建信号
            second.delegateSignal = [RACSubject subject];
            //订阅代理信号----订阅信号
            [second.delegateSignal subscribeNext:^(id x) {
                
                NSLog(@"%@",x);
                
            }];
            [self.navigationController pushViewController:second animated:YES];
            
        }];
    

    代替通知

    //注册通知
     [[[NSNotificationCenter defaultCenter] rac_addObserverForName:@"notification" object:nil] subscribeNext:^(NSNotification * notification) {
            
            NSLog(@"收到通知 notification.name=%@ notification.object=%@",notification.name,notification.object);
            
        }];
    //发送通知
    [[NSNotificationCenter defaultCenter] postNotificationName:@"notification" object:@"通知传值"];
    

    代替KVO

    这里 以监听UITextField的text变动为例。

    #pragma mark KVO监听
        
        [[self.textField rac_valuesAndChangesForKeyPath:@"text" options:NSKeyValueObservingOptionNew observer:@""] subscribeNext:^(RACTwoTuple<id,NSDictionary *> * _Nullable x) {
            
            NSLog(@"KVO监听结果:%@",x);
            
        }];
    

    监听某个对象的某个属性,返回的是信号 可用于搜索返回结果展示。联想一下音乐播放器搜歌。

    #pragma mark 监听某个对象的某个属性,返回的是信号
        [RACObserve(self,changeString)
         subscribeNext:^(NSString* x){
             
             NSLog(@"RACObserve ----%@--",x);
             
         }];
    //监听判断 
     [[RACObserve(self, changeString)filter:^BOOL(id  _Nullable value) {
            
            return [value  isEqualToString:@"开始"] ? YES : NO;
            
        }] subscribeNext:^(id  _Nullable x) {
            
            //满足上面条件才能执行
            NSLog(@"x---终于轮到我展示了");
            
        }] ;
    
    

    监听事件

    这里只展示开发者中常用的点击事件。以UIButton的点击事件和UILabel的手势为例。

    #pragma mark button 点击事件
    [[self.signalButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
          
          NSLog(@"button点击事件 ---%@",x);
    
          [self.navigationController pushViewController:second animated:YES];
          
      }];
    //button事件监听的另一种方法
    self.signalButton.rac_command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id  _Nullable input) {
          
          NSLog(@"接受button事件的第二张方法");
          
          return [RACSignal empty];
      }];
    
    #pragma mark UILabel 手势
      
      UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] init];
      
      [[tap rac_gestureSignal] subscribeNext:^(id x) {
          
          NSLog(@"label手势---%@",x);
        
      }];
    [self.myLabel addGestureRecognizer:tap];
    

    文本监测

    主要针对于 UITextField、UITextView文本的监测可代替自身的代理。

     #pragma mark UITextField 文本监测
         @weakify(self)
         [self.textField.rac_textSignal subscribeNext:^(NSString *x) {
          @strongify(self)
            NSLog(@"%@",x);
            
            self.changeString = x;
            
        }];
    

    替代遍历

    1、数组遍历
     NSArray *numbers = @[@1,@2,@3,@4,@5];
        
        [numbers.rac_sequence.signal subscribeNext:^(id  _Nullable x) {
            
            NSLog(@"NSArray ---- %@",x);
    
        }];
    
    2、字典遍历
     NSDictionary *dict = @{@"name":@"wang",@"age":@"18"};
        
        [dict.rac_sequence.signal subscribeNext:^(RACTuple *x) {
            
            RACTupleUnpack(NSString *key,NSString*value) = x;
            
            NSLog(@"NSDictionary ----- key=%@ value=%@",key,value);
            
        }];
    
    3、字典转模型
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"ClassList.plist" ofType:nil];
        NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];
        NSMutableArray *modelArray = [NSMutableArray array];
        
        [dictArr.rac_sequence.signal subscribeNext:^(id  _Nullable x) {
            
            NSLog(@"字典转模型 %@",x);
            
            classModel *model = [classModel modelObjectWithDictionary:x];
            
            [modelArray addObject:model];
            
            //        NSLog(@"名字----%@",model.name);
            
        }] ;
    //简单粗暴的写法
     NSArray *flags = [[dictArr.rac_sequence map:^id(id value) {
            
            return [classModel  modelObjectWithDictionary:value];
            
        }] array];
    
    

    进入相册选择照片

    self.pictureButton.rac_command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id  _Nullable input) {
            
            UIImagePickerController *pickerController = [UIImagePickerController new];
            pickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
            [pickerController.rac_imageSelectedSignal subscribeNext:^(NSDictionary * info) {
                
                UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
                
                self.myImageView.image = image;
                [pickerController dismissViewControllerAnimated:YES completion:nil];
                
            }];
            //取消
            [[pickerController.rac_delegateProxy signalForSelector:@selector(imagePickerControllerDidCancel:)] subscribeNext:^(id  _Nullable x) {
                
                [pickerController dismissViewControllerAnimated:YES completion:nil];
            }];
            //跳转
            [self presentViewController:pickerController animated:YES completion:nil];
            
            
            return [RACSignal empty];
        }];
    

    至今已经熟悉运用的这么多。是不是比你用的要简单。先掌握熟悉运用。至于原理学习了解了再告诉大家。

    参考文档

    https://www.jianshu.com/p/e10e5ca413b7
    https://www.jianshu.com/p/a4fefb434652
    https://blog.csdn.net/jia12216/article/details/55520151
    https://blog.csdn.net/wzc10101415/article/details/55051339
    https://blog.csdn.net/y_csdnblog_xx/article/details/51480181
    https://www.cnblogs.com/develop-SZT/p/5292622.html

    相关文章

      网友评论

          本文标题:ReactiveCocoa之基本使用

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