ReactiveCocoa网上资料很多,今天就介绍一下ReactiveCocoa简单的用法。
在没有使用ReactiveCocoa之前我们监听UITextField文本变化是这样做的
[textField addTarget:self action:@selector(changedTextField:) forControlEvents:UIControlEventEditingChanged];
-(void)changedTextField:(id)textField
{
NSLog(@"值是---%@",textField.text);
}
使用了ReactiveCocoa之后就变得简单了
// 监听文本框的输入,而且只有大于3个长度的时候才会打印
[[self.textField.rac_textSignal filter:^BOOL(NSString * _Nullable value) {
return value.length > 3;
}]subscribeNext:^(NSString * _Nullable x) {
NSLog(@"%@", x);
}];
[[self.button rac_signalForControlEvents:UIControlEventTouchUpInside]subscribeNext:^(__kindof UIControl * _Nullable x) {
NSLog(@"%@", x);
}];
Account
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface Account : NSObject
//账号
@property (nonatomic, copy) NSString *userName;
//密码
@property (nonatomic, copy) NSString *password;
@end
NS_ASSUME_NONNULL_END
LoginViewModel.h
#import <Foundation/Foundation.h>
#import "Account.h"
NS_ASSUME_NONNULL_BEGIN
@interface LoginViewModel : NSObject
//用户账号数据模型
@property (nonatomic, strong) Account *account;
// 是否允许登录的信号
@property (nonatomic, strong, readonly) RACSignal *enableLoginSignal;
@property (nonatomic, strong, readonly) RACCommand *LoginCommand;
@end
NS_ASSUME_NONNULL_END
LoginViewModel.m
#import "LoginViewModel.h"
@implementation LoginViewModel
- (Account *)account
{
if (_account == nil) {
_account = [[Account alloc] init];
}
return _account;
}
- (instancetype)init
{
if (self = [super init]) {
[self initialBind];
}
return self;
}
// 初始化绑定
- (void)initialBind
{
// 监听账号的属性值改变,把他们聚合成一个信号。
_enableLoginSignal = [RACSignal combineLatest:@[RACObserve(self.account, userName),RACObserve(self.account, password)] reduce:^id(NSString *userName,NSString *password){
return @(userName.length && password.length);
}];
// 处理登录业务逻辑
_LoginCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
NSLog(@"点击了登录");
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// 模仿网络延迟
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subscriber sendNext:@"登录成功"];
// 数据传送完毕,必须调用完成,否则命令永远处于执行状态
[subscriber sendCompleted];
});
return nil;
}];
}];
// 监听登录产生的数据
[_LoginCommand.executionSignals.switchToLatest subscribeNext:^(id x) {
if ([x isEqualToString:@"登录成功"]) {
NSLog(@"登录成功");
}
}];
}
@end
LoginViewController
#import "LoginViewController.h"
#import "LoginViewModel.h"
@interface LoginViewController ()
@property (weak, nonatomic) IBOutlet UITextField *accountField;
@property (weak, nonatomic) IBOutlet UITextField *pwdField;
@property (weak, nonatomic) IBOutlet UIButton *loginBtn;
@property (nonatomic, strong) LoginViewModel *loginViewModel;
@end
@implementation LoginViewController
- (LoginViewModel *)loginViewModel
{
if (_loginViewModel == nil) {
_loginViewModel = [[LoginViewModel alloc] init];
}
return _loginViewModel;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
[self bindModel];
}
// 视图模型绑定
- (void)bindModel
{
// 给模型的属性绑定信号
// 只要账号文本框一改变,就会给account赋值
RAC(self.loginViewModel.account, userName) = _accountField.rac_textSignal;
RAC(self.loginViewModel.account, password) = _pwdField.rac_textSignal;
// 绑定登录按钮
RAC(self.loginBtn,enabled) = self.loginViewModel.enableLoginSignal;
// 监听登录按钮点击
[[_loginBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
// 执行登录事件
[self.loginViewModel.LoginCommand execute:nil];
}];
}
一提到ReactiveCocoa就有人会说MVVM,但是单独使用ReactiveCocoa也是可以,不一定有了ReactiveCocoa的就是MVVM。项目中很少使用ReactiveCocoa,之前有人提到使用ReactiveCocoa如果出错了很难定位到代码错误。但是简单的使用还是可以了。比如监听UITextField。按钮点击事件啊。