美文网首页
ReactiveObjc初探

ReactiveObjc初探

作者: xuzhenhao | 来源:发表于2018-06-07 11:10 被阅读4次

    一. 存在的问题

    1. UI更新必须依赖程序员在指定位置手动触发。UI更新的逻辑会遍布各地难以维护,而且调用者必须明确的知道更新的逻辑,因为updatA,updateB,先调后调有时也会发生截然不同的效果。

    2. 举个🌰,假如有一个类似网易云音乐的列表页。歌曲列表请求成功后,赋值tabelView的数据源。注意,此时我们还有执行[tableView reloadData],此外,可能还需要调更新歌曲数,更新专辑封面等等。只要和这个数据源有关的UI元素,我们都需要手动触发一遍。更重要的是要更新哪些UI,需要我们自己判断,极容易引发bug。上述是网络请求的,在类似的多交互页面中,常常还包括侧滑删除、批量增加、名称修改等等对数据源的操作,而这些都意味着我们需要手动触发UI更新。当然,有些共同的更新,我们可以抽成一个方法,但还是难以从根本上避免伴随着用户事件及数据改变的,散落各地的UI更新逻辑。

    二. RAC的解决方案

    1. 还是上面那个场景,使用RAC后,只需要关心数据源如果变化,无需关心数据源变化后所引发的UI层面的连锁反应。加载更多,往数据源中加对应数据;删除某首歌,删除数据源中的对应数据。修改数据后,订阅(subscribe)了数据源的相关元素会自动接收到数据变化的信号,并作出对应改变。

    2. 光是上述效果我们用KVO也能做到,RAC更独特的地方在于用信号量(Signal)统一了所有变化,包括网络回调、KVO、通知、block等等,抽象成信号量后,我们可以统一进行逻辑操作,包括combine、filter、map等等,这些操作才是强力的工具。整个流程为事件流->信号流->逻辑操作->订阅。

    三. 适合使用RAC的场景举例

    1. 登录注册:登录注册常见的需求有必须同时满足xxx条件,按钮才能启用。
    
    @weakify(self);
    
        //自动响应登录按钮是否可用
    
        RAC(self.loginButton, enabled) = [RACSignal
    
                              combineLatest:@[self.accountTextField.rac_textSignal,
    
                                              self.pwdTextField.rac_textSignal]
    
                               reduce:^(NSString *userName,NSString *pwd){
    
                                return @(userName.length > 0 && pwd.length > 0);
    
                                 }];
    
        //account属性自动响应更新值
    
        [[self.accountTextField.rac_textSignal filter:^BOOL(NSString * _Nullable value) {
    
            return value.length > 0;
    
        }] subscribeNext:^(NSString * _Nullable x) {
    
            @strongify(self);
    
            self.loginViewModel.account = x;
    
        }];
    
        //password属性自动响应更新值
    
        [[self.pwdTextField.rac_textSignal filter:^BOOL(NSString * _Nullable value) {
    
            return value.length > 0;
    
        }] subscribeNext:^(NSString * _Nullable x) {
    
            @strongify(self);
    
            self.loginViewModel.password = x;
    
        }];
    
        //按钮点击事件转成信号流,调用VM中的方法执行。
    
        [[self.loginButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
    
            @strongify(self);
    
            [[self.loginViewModel.loginCommand executing] subscribeNext:^(id  _Nullable x) {
    
                NSLog(@"登录成功");
    
            }];
    
            [[self.loginViewModel.loginCommand execute:nil] subscribeError:^(NSError * _Nullable error) {
    
                NSLog(@"登录失败");
    
            }];
    
        }];
    
    
    
    vm.m
    
    - (void)setupCommand{ 
              @weakify(self); 
            _loginCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal *                        _Nonnull(id _Nullable input) {
             return [RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
    
                @strongify(self);
    
                [self loginWithUserName:self.account password:self.password done:^(NSDictionary *result) {
    
                    NSString *userId = [result objectForKey:@"user_id"];
    
                    if (userId) {
                        [subscriber sendCompleted];
                    }else{
                        [subscriber sendError:nil];
                    }
                }];
                return nil;
            }];
        }];
    }
    

    相关文章

      网友评论

          本文标题:ReactiveObjc初探

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