RACCommand的初步使用

作者: 路上捡只猫 | 来源:发表于2018-07-31 13:44 被阅读0次

    RACCommand 是一个在 ReactiveCocoa 中比较复杂的类,大多数使用 ReactiveCocoa 的人,尤其是初学者并不会经常使用它。

    在很多情况下,虽然使用 RACSignal 和 RACSubject 就能解决绝大部分问题,但是 RACCommand 的使用会为我们带来巨大的便利,尤其是在与副作用相关的操作中。

    image

    RACCommand 简介

    RACCommand 并不表示数据流,它只是一个继承自 NSObject的类,但是它却可以用来创建和订阅用于响应某些事件的信号。

    它本身并不是一个 RACStream 或者 RACSignal 的子类,而是一个用于管理 RACSignal 的创建与订阅的类。

    在 ReactiveCocoa 中的 FrameworkOverview 部分对 RACCommand 有这样的解释:

    A command, represented by the RACCommand class, creates and subscribes to a signal in response to some action. This makes it easy to perform side-effecting work as the user interacts with the app. 
    

    在用于与 UIKit 组件进行交互或者执行包含副作用的操作时,RACCommand 能够帮助我们更快的处理并且响应任务,减少编码以及工程的复杂度。

    RACCommand 的初始化与执行

    在 -initWithSignalBlock: 方法的方法签名上,你可以看到在每次 RACCommand 初始化时都会传入一个类型为 RACSignal * (^)(InputType _Nullable input) 的 signalBlock:

    -(instancetype)initWithSignalBlock:(RACSignal*(^)(InputType _Nullable input))signalBlock;
    

    输入为 InputType 返回值为 RACSignal *,而 InputType 也就是在调用 -execute: 方法时传入的对象:

    
    -(RACSignal*)execute:(nullable InputType)input 
    
    

    我们以下面的代码为例,先来看一下 RACCommand 是如何工作的:

    RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(NSNumber * _Nullable input) {
        return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
            NSInteger integer = [input integerValue];
            for (NSInteger i = 0; i < integer; i++) {
                [subscriber sendNext:@(i)];
            }
            [subscriber sendCompleted];
            return nil;
        }];
    }];
    [[command.executionSignals switchToLatest] subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@", x);
    }];
    
    [command execute:@1];
    [RACScheduler.mainThreadScheduler afterDelay:0.1
                                        schedule:^{
                                            [command execute:@2];
                                        }];
    [RACScheduler.mainThreadScheduler afterDelay:0.2
                                        schedule:^{
                                            [command execute:@3];
                                        }];
    
    

    首先使用 -initWithSignalBlock: 方法创建一个 RACCommand 的对象,传入一个类型为 InputType -> RACSignal<ValueType> 的 block,这个信号根据输入会发送对应次数的消息,

    RACCommand 的使用

    RACCommand 非常适合封装网络请求,我们可以使用下面的代码封装一个网络请求:

    -(instancetype)init{
        if (self = [super init]) {
            RACSignal *usernameSingal = [RACObserve(self, name) map:^id _Nullable(id  _Nullable value) {
                if ([(NSString *)value length] >6) {
                    return @(YES);
                }
                return @(NO);
            }];
            RACSignal *passwordSingl = [RACObserve(self, password) map:^id _Nullable(id  _Nullable value) {
                if ([(NSString *)value length] > 6) return @(YES);
                return @(NO);
            }];
            RACSignal *loginSingl = [RACSignal combineLatest:@[passwordSingl,usernameSingal] reduce:^id(NSNumber *username,NSNumber *passwordSingl){
                return @([username boolValue] && [passwordSingl boolValue]);
            } ];
            _loginButtonCommand = [[RACCommand alloc]initWithEnabled:loginSingl signalBlock:^RACSignal * _Nonnull(id  _Nullable input) {
                return [self loginWithUserName:self.name password:self.password];
            }]  ;
        }
        
        return self;
    }
    -(RACSignal *)loginWithUserName:(NSString *)name password:(NSString *)passWord{
    
        if (name.length > 6 && passWord.length > 6) {
            return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
                [subscriber sendNext:[NSString stringWithFormat:@"姓名:%@ 密码:%@",self.password,self.name]];
                [subscriber sendCompleted];
                return nil;
            }];
        }
        return nil;
    }
    
     button.rac_command = self.modelViews.loginButtonCommand;
        RAC(self.modelViews,name) = textfield.rac_textSignal;
        RAC(self.modelViews,password) = textfield1.rac_textSignal;
        [[self.modelViews.loginButtonCommand executionSignals] subscribeNext:^(id  _Nullable x) {
            [x subscribeNext:^(id  _Nullable x) {
                NSLog(@"%@",x);
            }];
        }];
    

    相关文章

      网友评论

        本文标题:RACCommand的初步使用

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