上一篇文章我们使用ReactiveCocoa搭建了一个简单的登录页面,这一次我们来搭建注册页面。
Account和password的有效规制还是和之前一样,长度必须大于5,否则输入框背景色是红色的,这一步直接用之前的代码就可以了。
注册按钮的响应和登录的响应应该是一样的逻辑,对于之前的伪代码来讲,也几乎没什么改动。
但是注册和登录最起码有个不同的东西,就是注册的用户名可能已经被占用,我们想用户在输入完了用户名之后,从后台对用户名是否可用进行判断,如果可用,才允许用户点击“注册”按钮。
仿照登录时候将登录方法封装成为信号的做法,或许可以把用户名检查的功能也封装成为一个信号,但我们这里尝试另外一种做法:使用RACSubject对象。RACSubject对象继承于RACSignal,相比于RACSignal,RACSubject具有主动发送信号值的功能。下面新建一个RACSubject对象。
|
|
这个信号代表了用户名是否可以用,且这个信号的值可以由代码主动去控制发出。注册按钮应该是用户名合法且可用,且密码合法的情况下才可以点击,所以把这3个信号combine一起
|
|
我们在用户名框的旁边放置一个imageView,用它的背景颜色来表示这个用户名是否可用,绿色代表可用,蓝色代表正在查找,黄色代表不可用。我们可以将这个属性和刚刚创建的isAccountAvailableSubject联系起来。
|
|
其中有一些枚举定义如下:
|
|
如果用户名不合法,判断用户名是否可用的imageView应该不要显示出来
|
|
剩下就是根据用户名输入去查询用户名是否合法了。这个方法我们已经写好,问题就在于它的调用时间,它应该是在用户名输入合法的时候调用,但如果去订阅accountValidSignal,那么在切换输入框的时候也会调用。所以不能直接订阅,这里再介绍一个方法
|
|
[SingleA sample:SingleB];
这个意思是只有当SingleB有信号的时候才会去获取SingleA最新值。我们可以把SingleA设为accountValidSignal
,SingleB设为[self.accountTV.rac_textSignal distinctUntilChanged]
,
distinctUntilChanged表示信号的值比上一次的信号值有更新了才会发送。
如果不加distinctUntilChanged,那么焦点离开也会发出rac_textSignal
这样就会在只有用户名改变的时候才会去获取accountValidSignal的最新值,然后加上filter进一步对用户名是否合法再过滤就可以了。
|
|
上面方法里面在回调里面使用isAccountAvailableSubject发送检查结果,accountAvailableImgView和注册按钮就会根据检查结果进行更新。
至此,一个简单的注册框就完成了。
当然这里面还有问题:假如第一次输入了一个合法的用户名,然后发起用户名检查,这时候立刻加上一个字符,那么又会发起第二次用户名检查,这个时候恰好第一次用户名检查的结果回来了,显示用户名可用,注册按钮可以点击。但是输入框里面已经是新的用户名了。这个问题留给大家思考。
循环引用
这个问题老生常谈了,有了block,就要小心这个问题。RAC采用了大量的block,一不小心就循环引用了。
为此,RAC里面提供了一个十分好用的宏来声明self的弱引用。这个宏定义在RACmetamacros.h里面。
这对宏是
|
|
使用的方法如下,在block外边使用@weakify(self),然后在block里面使用@strongify(self)。以后block里面的self就是弱引用的了。
|
|
具体原理是weakify(self)
声明了一个self的弱引用变量,strongify(self)
把这个弱引用变量变为了局部的强引用变量。至于这个@,其实是autoreleasepool {}
(在debug编译下) 或者 try {} @catch (...) {}
(在release编译下)