1.Demo展示
Demo地址: https://github.com/shidavid/DVDataBind
如果对 DVDataBind 有兴趣请看:基于KVO的轻量级iOS双向数据绑定响应式编程框架
ps: iOS录屏录不了输入密码过程
image
2.代码如下
- LoginViewController:View 和 ViewModel 的绑定
@interface LoginViewController ()
@property(nonatomic, strong) LoginView *loginView;
@property(nonatomic, strong) LoginViewModel *loginViewModel;
@end
@implementation LoginViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self initViews];
[self initViewModels];
[self bindViewModel];
}
#pragma mark - <-- Init -->
- (void)initViews {
self.loginView = (LoginView *)self.view;
self.loginView.backgroundColor = [UIColor Blue];
}
- (void)initViewModels {
self.loginViewModel = [[LoginViewModel alloc] init];
}
- (void)bindViewModel {
__weak __typeof(self)weakSelf = self;
// 这里 View 跟 ViewModel 双向绑定
DVDataBind
._in_ui(self.loginView.userNameText, @"text", UIControlEventEditingChanged)
._out(self.loginViewModel, @"userName")
._filter(^BOOL(NSString *text) {
//这里判断用户名是否符合规范、校验、限制等等操作,return YES 数据才能更新
return [weakSelf.loginViewModel filterUserName:text];
})
._out_key_any(@"login.userName.text", ^{
weakSelf.loginView.btnLogin.enabled = [weakSelf.loginViewModel btnLoginEnable];
});
DVDataBind
._in_ui(self.loginView.passwordText, @"text", UIControlEventEditingChanged)
._out_cv(self.loginViewModel, @"password", ^(NSString *text){
// textField.secureTextEntry = YES时, text为密文, 需要转换
return [NSString stringWithUTF8String:text.UTF8String];
})
._filter(^BOOL(NSString *text) {
NSString *tempText = [NSString stringWithUTF8String:text.UTF8String];
return [weakSelf.loginViewModel filterPassword:tempText];
})
._out_key_any(@"login.passwordText.text", ^{
weakSelf.loginView.btnLogin.enabled = [weakSelf.loginViewModel btnLoginEnable];
});
DVDataBind
._in_ui(self.loginView.btnLogin, @"highlighted", UIControlEventTouchUpInside)
._out_key_any(@"login.btnLogin.login", ^{
[weakSelf.loginViewModel login];
});
}
@end
- LoginView :UI 的初始化、配置和布局
@interface LoginView : UIView
@property (weak, nonatomic) IBOutlet UITextField *userNameText;
@property (weak, nonatomic) IBOutlet UITextField *passwordText;
@property (weak, nonatomic) IBOutlet UIButton *btnLogin;
@end
- LoginViewModel : ViewModel是关于View的Model, 这里是业务逻辑、网络请求等等
@interface LoginViewModel : NSObject
@property(nonatomic, copy) NSString *userName;
@property(nonatomic, copy) NSString *password;
- (BOOL)btnLoginEnable;
- (BOOL)filterUserName:(NSString *)userName;
- (BOOL)filterPassword:(NSString *)password;
- (void)login;
@end
@implementation LoginViewModel
- (BOOL)btnLoginEnable {
return (self.userName && self.userName.length > 0
&& self.password && self.password.length > 0);
}
- (BOOL)filterUserName:(NSString *)userName {
// 这里可加 userName判断处理,限制
return userName.length <= 15;
}
- (BOOL)filterPassword:(NSString *)password {
// 这里可加 password判断处理,限制
return password.length <= 20;
}
- (void)login {
// Model是关于服务器的数据模型, ViewModel是关于View的Model
LoginModel *model = [[LoginModel alloc] init];
model.userName = self.userName;
model.password = self.password;
// 这里post model 到服务器
NSLog(@"登录成功, userName -> %@, password -> %@", model.userName, model.password);
}
@end
- LoginModel:关于服务器的数据模型,有网络请求才存在
@interface LoginModel : NSObject
@property(nonatomic, copy) NSString *userName;
@property(nonatomic, copy) NSString *password;
@end