看到评论留言,希望笔者能多一些RAC知识的输出,但是笔者忙于给项目写bug一直持续了1个多月,每天都将近11,12点到家。周六得加班。而导致许久未更,甚是惭愧。
2021.5.29记录
再次进入该篇未写完的文章,查询历史版本一看,原来已经上一次写该篇文章居然是10个月之前。时间总在不经意之间流逝滴如此之快。看挺多读者又在留言中希望笔者输出一些比较有价值的实战,评论区有有几个小伙伴一直在等着更新。下面那就让我们一起进入接下来的学习吧!
目录
一、关于项目
二、MVVM介绍
三、RAC+MVVM登录逻辑
一、关于项目
主要是为了分享RAC在实际中的应用场景
二、MVVM介绍
模型(M):保存视图数据。
视图+控制器(V):展示内容 + 如何展示
-
视图模型(VM):处理展示的业务逻辑,包括按钮的点击,数据的请求和解析等等。
三、RAC+MVVM登录逻辑
3.1 需求
- 1 手机号限制长度为11位,密码限制长度为6位
- 2 登录按钮默认为灰色,且不交互状态
- 3 登录按钮的交互事件 需满足手机号和验证码同时有值才可交互
3.2 代码实现
3.2.1 控制器代码
//主要代码段
#import "LoginViewController.h"
#import "LoginViewModel.h"
@interface LoginViewController ()
@property(nonatomic ,strong)UITextField *accountTextFiled;
@property(nonatomic ,strong)UITextField *passwordTextField;
@property(nonatomic ,strong)UIImageView *imgView;
@property(nonatomic ,strong)UIButton *loginBtn;
@property(nonatomic ,strong)LoginViewModel *viewModel;
@end
@implementation LoginViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self setupSubView];
[self bindViewModel];
}
#pragma mark - bindViewModel
- (void)bindViewModel{
//绑定输入框
RAC(self.viewModel,account) = [RACSignal merge:@[self.accountTextFiled.rac_textSignal,RACObserve(self.accountTextFiled, text)]];
RAC(self.viewModel,password) = [RACSignal merge:@[self.passwordTextField.rac_textSignal,RACObserve(self.passwordTextField, text)]];
//监听button是否可用
RAC(self.loginBtn, enabled) = self.viewModel.loginBtnEnableSignal;
@weakify(self);
[RACObserve(self.loginBtn, enabled) subscribeNext:^(id _Nullable x) {
@strongify(self);
[self.loginBtn setBackgroundColor:[x boolValue]?kThemeColor:[UIColor colorWithHex:0xD0D0D0]];
}];
[[self.loginBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
@strongify(self);
[HHHudManager showHudWithText:[NSString stringWithFormat:@"输入的账号为:%@\n密码为:%@",self.viewModel.account,self.viewModel.password]];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self dismissViewControllerAnimated:true completion:^{}];
});
}];
//显示输入长度
[self.accountTextFiled.rac_textSignal subscribeNext:^(NSString * _Nullable x) {
@strongify(self);
if ([x length] > 11) {
self.accountTextFiled.text = [x substringToIndex:11];
}
}];
[self.passwordTextField.rac_textSignal subscribeNext:^(NSString * _Nullable x) {
@strongify(self);
if ([x length] > 6) {
self.passwordTextField.text = [x substringToIndex:6];
}
}];
}
3.2.2 ViewModel代码
//LoginViewModel.h
//BaseViewModel里面定义了一些基础性的东西(eg:loading/网络异常/无数据/服务器异常/toast提示等,后面做购物车以及订单的时候会用到。。)
@interface LoginViewModel : BaseViewModel
@property (nonatomic , readonly, copy) NSString * account;
@property (nonatomic , readonly, copy) NSString * password;
@property (nonatomic , strong) RACSignal *loginBtnEnableSignal;
@end
//LoginViewModel.m
#import "LoginViewModel.h"
@interface LoginViewModel()
@property (nonatomic , readwrite, copy) NSString * account;
@property (nonatomic , readwrite, copy) NSString * password;
@end
@implementation LoginViewModel
- (instancetype)init{
if ( self = [super init]) {
[self bindModel];
}
return self;
}
- (void)bindModel{}
- (RACSignal *)loginBtnEnableSignal{
if (!_loginBtnEnableSignal) {
_loginBtnEnableSignal = [RACSignal combineLatest:@[RACObserve(self, account),RACObserve(self, password)] reduce:^id _Nonnull{
return @(self.account.length && self.password.length);
}];
}
return _loginBtnEnableSignal;
}
@end