ReactiveCocoa 学习心得 -- 2

在上一篇篇文章中,简单讲述了一下ReactiveCocoa集成到项目中的几种方法,环境已经具备,下面我们一起来接触一下RAC基本的几个用法

如下图所示:
现在有这样的一个需求,在输入框里没有文字的时候,输入框左边对应的文字为灰色,有文字的时候,变为黑色。并且当且仅当账号和密码都有输入的时候,登录按钮才能点击。
这里写图片描述

很常见的需求,第一反应我是这样的:

1,给两个输入框和两个label分别设置不同的tag值,根据textField的代理方法监听输入框里的内容,从而判断label的显示颜色。
2,设置一个变量初始值为0,当textField有值就+1,清空值就-1,然后kvo监听这个变量,当变量等于2的时候,loginButton可以点击,否则不可以点击。

或许你有更好的解决方案,也许你觉得代码还算简单。现在我们尝试着用RAC去解决

首先监听输入框的文字,看下面一段代码:

    [self.nameTextField.rac_textSignal subscribeNext:^(NSString *x) {
        if (x.length>0) {
            self.nameLabel.textColor = [UIColor blackColor];
        }else{
            self.nameLabel.textColor = [UIColor lightGrayColor];
        }
    }];


    [self.passwordTextField.rac_textSignal subscribeNext:^(NSString *x) {
        if (x.length>0) {
            self.passwordLabel.textColor = [UIColor blackColor];
        }else{
            self.passwordLabel.textColor = [UIColor lightGrayColor];
        }
    }];

这里写图片描述
试下效果,竟然成功了。现在有了疑问,rac_textSignal是个什么东西,subscribeNext又是个什么东西?

rac_textSignal 属于RACSignal的一种,通常被称作为信号。你可以认为它是RAC封装好的一个信号(点进方法,你也会看到textViewDidChange的监听方法),用于监听输入框内文字的变化。


subscribeNext : block,可以理解为是信号的订阅。没有被订阅的信号,我们叫做冷信号,输入框文字发生变化后,不会触发任何动作。只有被订阅了,信号由冷变热,才能去处理一些事情。比如我们改变nameLabel 和 passwordLabel 的字体颜色 这件事情。

到这里,也许你会说,subscribeNext里面的一个大大的 if else 着实看着比较low, 和 rac_textSignal 比起来画风不太对。我们在看下面一种写法。

RAC(self.nameLabel, textColor) =[self.nameTextField.rac_textSignal map:^id(NSString *text) {

        return text.length>0?[UIColor blackColor]:[UIColor lightGrayColor];

    }];


RAC(self.passwordLabel, textColor) = [self.passwordTextField.rac_textSignal map:^id(NSString *text) {

        return text.length>0?[UIColor blackColor]:[UIColor lightGrayColor];

     }];

不用怀疑,到达了一样的效果,这里又有了两个疑问,RAC 是什么, map又是什么?

RAC,是ReactiveCocoa的一个宏,它的功能是直接把输出的信号应用到该对象的属性上。这个宏有两个参数,第一个是对象,第二个是该属性名。


map 自然是去输出一个信号了,准确来说map更像一个信号转换器,把原始的信号(text) 转化为新的信号(color)。

这里写图片描述

如上图所示: map的作用就是把当前的信号转化为你想要的信号。


到这里, 需求已经实现了一大半了,下面就是如何利用RAC,去控制登录按钮的状态

同样,先看代码:

   RACSignal *nameValidSignal = [self.nameTextField.rac_textSignal map:^id(NSString *value) {
       return @(value.length>0);
   }];


    RACSignal *passwordValidSignal = [self.passwordTextField.rac_textSignal map:^id(NSString *value) {
        return @(value.length>0);
    }];


    [[RACSignal combineLatest:@[nameValidSignal,passwordValidSignal] reduce:^id(NSNumber *nameValid,NSNumber *passwordVaild){

        return @([nameValid boolValue]&&[passwordVaild boolValue]);

    }] subscribeNext:^(NSNumber *x) {

        self.loginButton.backgroundColor = [x boolValue]?EnableColor:DisableColor;
        self.loginButton.enabled = [x boolValue];

    }];

从上面代码可以看出,我先创建了两个信号,使用map方法把这两个信号【输入的内容信号】 分别转化为 【 是否有文字输入的信号】(@0 或者 @1), 当这两个信号都得值都为(@1)的时候,登录键盘就可以点击了,否则就无法点击。

如何合并这两个信号呢?这里又引入了一个新的方法 combineLatest:reduce:

这里写图片描述

combineLatest 的作用是 把多个信号源合并到一起,并产生一个新的信号。
当这些信号源中任何一个发生变化,就会执行reduce下的block代码块。
并返回一个我们想要的全新的信号。

就像上面的代码一样,把 nameValidSignal(是否有姓名的信号) 和 passwordValidSignal (是否有密码的信号)这两个信号合并到一起,然后通过 reduce 返回一个新的信号 (登录按钮是否可以点击的信号),当然,这个信号还是冷信号,通过后面的 subscribeNext 让信号变成热信号,我们就可以拿到这个信号,去控制登录按钮的状态了。

当然,这个地方你也可以改写成

    RACSignal *signal = [RACSignal combineLatest:@[nameSignal,passwordsSignal] reduce:^id(NSNumber *nameValid,NSNumber *passwordVaild){
        return  @([nameValid boolValue]&&[passwordVaild boolValue]);
    }];


    RAC(self.loginButton,backgroundColor) = [signal map:^id(id value) {
        return [value boolValue]?EnableColor:DisableColor;
    }];

    RAC(self.loginButton,enabled) = [signal map:^id(id value) {
        return value;
    }];

RAC提供了很灵活的用法,试着用不同的方法去解决同一个问题,也是学习的一种方式。

到这里,登录的界面逻辑已经差不多了,下面的就是登陆的action了

[[self.loginButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {

        NSLog(@"Click Login Button");
    }];

rac_signalForControlEvents 与上文 rac_textSignal 类似,都是RAC内部实现过的信号,我们只用把这个冷信号转化为热信号就好了。

总结:这篇博客主要记录了RAC里 rac_textSignal、rac_signalForControlEvents、subscribeNext:、RAC宏定义、map:、combineLatest:reduce的意义和实际用法。然而关于ReactiveCocoa,还有很多的东西值得我们探索和学习。保持进步,哪怕每天一点点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值