美文网首页iOS学习笔记
RAC在项目中的初步应用

RAC在项目中的初步应用

作者: isletn | 来源:发表于2017-06-09 16:42 被阅读0次

    首先简单介绍一下RAC是个什么东西。RAC全称ReactiveCocoa,是GitHub开源的一个函数响应式编程(FRP)库。

    Signal 与 Subscriber

    可以说这是RAC核心最核心的两个概念。Signal好比是光纤中传输的数字信号,而Subscriber是我们每个人家里的光猫。我们打开了家里的光猫才能正常上网,Signal 与 Subscriber就是这个互相配合工作的。

    首先我们看看RACSubscriber的API

    @protocol RACSubscriber <NSObject>
    @required
    - (void)sendNext:(nullable id)value;
    - (void)sendError:(nullable NSError *)error;
    - (void)sendCompleted;
    - (void)didSubscribeWithDisposable:(RACCompoundDisposable *)disposable;
    @end
    
    

    Subscriber通过sendNext、sendError、sendCompleted等方法获取由Signal传输过来的数据。用法如下:

    RACSignal *signal = RACObserve(self, clueArray);
    [signal subscribeNext:^(id  _Nullable x) {
         NSLog(@"%@",x);
    }];
    

    上述例子我们监听了一个全局变量数组,在它发生变化时我们可以做自己想做的操作,比如更新UI、给服务器上传数据变化等等。

    这里就暂时初步做个介绍吧, 深入的理解等我搞清楚了在写吧,本篇只介绍简单的用法。

    RAC实用的API:

    • 1 代替target-action
    [[self.confirmButton rac_signalForControlEvents:UIControlEventTouchUpInside]
      subscribeNext:^(id x) {
      // 回调内容写在这里
      }];
    
    • 2 代替delegate
    [[self.scrollView rac_signalForSelector:@selector(scrollViewDidScroll:) fromProtocol:@protocol(UIScrollViewDelegate)]
      subscribeNext:^(id x) {
      // 回调内容写在这里
      }];
    
    • 3 代替block
    [[self asyncProcess] subscribeNext:^(id x) {
      // 回调内容写在这里
      } error:^(NSError *error) {
      // 错误处理写到这里
      }];
    
    • 4 代替notification center
    //订阅通知
    @weakify(self)
        [[[kNotificationCenter rac_addObserverForName:kOperateReturnNotificationNameUpdate object:nil] takeUntil:self.rac_willDeallocSignal] subscribeNext:^(NSNotification * _Nullable x) {
            @strongify(self)
            [self fetchData];
        }];
    
    • 5 代替KVO
    [RACObserve(self, name) subscribeNext:^(id x) {
      // 回调内容写在这里
      }];
    
    • 6 单向绑定
    //当两个TextField的text长度都大于零,确认按钮才能点击
    RAC(self.confirmItem, enabled) = [RACSignal combineLatest:@[self.userNameTextField.rac_textSignal,
                                                                    self.passwordTextField.rac_textSignal,]
                                                           reduce:^id _Nullable{
                                                               return @(self.userNameTextField.text.length > 0 && self.passwordTextField.text.length > 0);
                                                           }];
    
    • 7 双向绑定
    //Model与View互相影响。当textField的text改变,model对应的值也跟着改变。反之,也成立。
    RACChannelTo(self.someLabel, text) = RACChannelTo(self.viewModel, someProperty);
    [self.textField.rac_newTextChannel subscribe:self.viewModel.someChannel];
    [self.viewModel.someChannel subscribe:self.textField.rac_newTextChannel];
    RACChannelTo(self, reviewID) = self.viewModel.someChannel;
    

    这里就列举以上几种,初步了解一下。


    RAC中常见的几个宏

    • 1 RACObserve(TARGET, KEYPATH);
    //用于监听person对象的name属性
    RACObserve(self.person, name)
    
    • 2 RAC(TARGET, ...);
    //将self.nameLabel.text 与 self.person.name绑定
     RAC(self.nameLabel, text) = RACObserve(self.person, name);
    
    • 3 weakify(...)
    //防止循环引用
    @weakify(self)
        [[[kNotificationCenter rac_addObserverForName:kOperateReturnNotificationNameUpdate object:nil] takeUntil:self.rac_willDeallocSignal] subscribeNext:^(NSNotification * _Nullable x) {
            @strongify(self)
            [self fetchData];
        }];
    

    虽然一般公司的项目都不那么复杂,用不上RAC,但是RAC作为一个工具库,也能提供一些比较便捷的解决问题的方案,所以了解一些RAC的知识还是有必要的。
    另外,MVVM解决了Controller臃肿的弊病,但也出现了一些新的问题。而MVVM+RAC完美的解决了这些问题,这也体现出RAC的强大。

    最后,附上一个MVVM场景下RAC的使用实例:

    • 1 ViewModel中的数据请求封装:
      + (RACSignal *)fetchData {
            RACReplaySubject *subject = [RACReplaySubject subject];
            NSURLRequest *request = [self popularURLRequest];
            [NSURLConnection sendAsynchronousRequest:request
                                           queue:[NSOperationQueue mainQueue]
                               completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError){
                                   if (data) {
                                       id results = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
                                       [subject sendNext:[[[results[@"photos"] rac_sequence] map:^id(NSDictionary *photoDictionary) {
                                           FRPPhotoModel * model = [FRPPhotoModel new];
                                           [self configurePhotoModel:model withDictionary:photoDictionary];
                                           [self downloadThumbnailForPhotoModel:model];
                                           return model;
                                       }] array]];
                                       [subject sendCompleted];
                                   } else {
                                       [subject sendError:connectionError];
                                   }
                               }];
        return subject;
    }
    
    • 2 监听数据源数组,刷新UI
    @weakify(self);
    [RACObserver(self, dataArray) subscribeNext:^(id x){
        @strongify(self);
        [self.tableView reloadData];
    }];
    
    • 3 VC中调用请求数据方法
     - (void)loadPopularPhotos{
        [[DataViewModel fetchData] subscribeNext:^(id x){
            self.dataArray = x;
        } error:^(NSError * error){
            NSLog(@"%@",error);
        }];
    }
    

    想深入学习的同学看这里:

    相关文章

      网友评论

        本文标题:RAC在项目中的初步应用

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