ReactiveCocoa入门教程二
来源:互联网 发布:matlab for mac 2016 编辑:程序博客网 时间:2024/04/29 21:58
欢迎访问我的个人blog
https://ekulelu.github.io/
上一篇文章我们使用ReactiveCocoa搭建了一个简单的登录页面,这一次我们来搭建注册页面。
本篇代码在https://github.com/Ekulelu/ReactiveCocoaRegister
Account和password的有效规制还是和之前一样,长度必须大于5,否则输入框背景色是红色的,这一步直接用之前的代码就可以了。
注册按钮的响应和登录的响应应该是一样的逻辑,对于之前的伪代码来讲,也几乎没什么改动。
但是注册和登录最起码有个不同的东西,就是注册的用户名可能已经被占用,我们想用户在输入完了用户名之后,从后台对用户名是否可用进行判断,如果可用,才允许用户点击“注册”按钮。
仿照登录时候将登录方法封装成为信号的做法,或许可以把用户名检查的功能也封装成为一个信号,但我们这里尝试另外一种做法:使用RACSubject对象。RACSubject对象继承于RACSignal,相比于RACSignal,RACSubject具有主动发送信号值的功能。下面新建一个RACSubject对象。
RACSubject *isAccountAvailableSubject = [RACSubject subject];
这个信号代表了用户名是否可以用,且这个信号的值可以由代码主动去控制发出。注册按钮应该是用户名合法且可用,且密码合法的情况下才可以点击,所以把这3个信号combine一起
RAC(self.registerBtn, enabled) = [RACSignal combineLatest:@[isAccountAvailableSubject, accountValidSignal,passwordVaildSignal] reduce:^id(NSNumber *accountUse, NSNumber* accountValid, NSNumber* passwordVaild){ return @(accountUse.intValue == AccountStatusAvailable && accountValid.boolValue && passwordVaild.boolValue); }];
我们在用户名框的旁边放置一个imageView,用它的背景颜色来表示这个用户名是否可用,绿色代表可用,蓝色代表正在查找,黄色代表不可用。我们可以将这个属性和刚刚创建的isAccountAvailableSubject联系起来。
RAC(self.accountAvailableImgView, backgroundColor) = [isAccountAvailableSubject map:^id(NSNumber *value) { switch (value.intValue) { case AccountStatusAvailable: return [UIColor greenColor]; break; case AccountStatusChecking: return [UIColor blueColor]; break; case AccountStatusUnavailable: default: return [UIColor yellowColor]; break; } }];
其中有一些枚举定义如下:
typedef NS_ENUM(int, AccountStatus) { AccountStatusAvailable = 0, AccountStatusChecking = 1, AccountStatusUnavailable = 2,};
如果用户名不合法,判断用户名是否可用的imageView应该不要显示出来
RAC(self.accountAvailableImgView, hidden) = [accountValidSignal map:^id(NSNumber *value) { return @(!value.boolValue); }];
剩下就是根据用户名输入去查询用户名是否合法了。这个方法我们已经写好,问题就在于它的调用时间,它应该是在用户名输入合法的时候调用,但如果去订阅accountValidSignal,那么在切换输入框的时候也会调用。所以不能直接订阅,这里再介绍一个方法
- (RACSignal *)sample:(RACSignal *)sampler;
[SingleA sample:SingleB]; 这个意思是只有当SingleB有信号的时候才会去获取SingleA最新值。我们可以把SingleA设为accountValidSignal,SingleB设为[self.accountTV.rac_textSignal distinctUntilChanged],
distinctUntilChanged表示信号的值比上一次的信号值有更新了才会发送。
如果不加distinctUntilChanged,那么焦点离开也会发出rac_textSignal
这样就会在只有用户名改变的时候才会去获取accountValidSignal的最新值,然后加上filter进一步对用户名是否合法再过滤就可以了。
[[[accountValidSignal sample:[self.accountTV.rac_textSignal distinctUntilChanged]] filter:^BOOL(NSNumber *value) { return value.boolValue; }] subscribeNext:^(id x) { [isAccountAvailableSubject sendNext:@(AccountStatusChecking)]; [self checkAccount:self.accountTV.text complete:^(Boolean success) { if (success) { [isAccountAvailableSubject sendNext:@(AccountStatusAvailable)]; NSLog(@"can use accout"); } else { [isAccountAvailableSubject sendNext:@(AccountStatusUnavailable)]; NSLog(@"can not use accout"); } }]; }];
上面方法里面在回调里面使用isAccountAvailableSubject发送检查结果,accountAvailableImgView和注册按钮就会根据检查结果进行更新。
至此,一个简单的注册框就完成了。
当然这里面还有问题:假如第一次输入了一个合法的用户名,然后发起用户名检查,这时候立刻加上一个字符,那么又会发起第二次用户名检查,这个时候恰好第一次用户名检查的结果回来了,显示用户名可用,注册按钮可以点击。但是输入框里面已经是新的用户名了。这个问题留给大家思考。
循环引用
这个问题老生常谈了,有了block,就要小心这个问题。RAC采用了大量的block,一不小心就循环引用了。
为此,RAC里面提供了一个十分好用的宏来声明self的弱引用。这个宏定义在RACmetamacros.h里面。
这对宏是
@weakify(self) @strongify(self)
使用的方法如下,在block外边使用@weakify(self),然后在block里面使用@strongify(self)。以后block里面的self就是弱引用的了。
@weakify(self)RACSignal *accountValidSignal = [self.accountTV.rac_textSignal map:^id(id value) { @strongify(self) return @(self.accountTV.text.length > 5);}];
具体原理是weakify(self)声明了一个self的弱引用变量,strongify(self)把这个弱引用变量变为了局部的强引用变量。至于这个@,其实是autoreleasepool {} (在debug编译下) 或者 try {} @catch (…) {} (在release编译下)
- ReactiveCocoa入门教程二
- ReactiveCocoa入门教程二
- ReactiveCocoa入门教程
- ReactiveCocoa入门教程
- ReactiveCocoa入门教程
- ReactiveCocoa<二>
- ReactiveCocoa入门教程:第一部分
- ReactiveCocoa入门教程:第一部分
- ReactiveCocoa入门教程:第一部分
- ReactiveCocoa入门教程:第一部分
- ReactiveCocoa入门教程:第一部分
- [ReactiveCocoa]入门教程:第一部分
- [ReactiveCocoa]入门教程:第二部分
- ReactiveCocoa入门教程:第一部分
- ReactiveCocoa入门教程一
- ReactiveCocoa入门教程:第一部分
- ReactiveCocoa入门教程:第一部分
- ReactiveCocoa入门教程:第二部分
- 我的2016——小程序员的碎碎念
- matplot 绘制图例和标注
- Coursera-ML:Week1-Octave/Matlab Tutorial
- 安卓复习之旅—自定义view(二)
- Android音频开发之使用OpenSL ES API
- ReactiveCocoa入门教程二
- 关于R与Tableau的集成----异常值检测
- 计算机是如何启动的
- jQuery AJAX实现调用页面后台方法
- Service服务:下载图片
- python中array和list的区别
- Java虚拟机-JVM各种参数配置大全详细
- iOS正向传值之:构造方法和property的区别
- C#—3种循环结构比较