RACCommand的初步使用

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  _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 的 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  _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的初步使用)