ReactiveCocoa 简单用法

2020-07-16 17:15:52 浏览数 (2)

ReactiveCocoa网上资料很多,今天就介绍一下ReactiveCocoa简单的用法。

监听UITextField的输入文本

在没有使用ReactiveCocoa之前我们监听UITextField文本变化是这样做的

代码语言:javascript复制
[textField addTarget:self action:@selector(changedTextField:) forControlEvents:UIControlEventEditingChanged];

-(void)changedTextField:(id)textField
{
    NSLog(@"值是---%@",textField.text); 
}

使用了ReactiveCocoa之后就变得简单了

代码语言:javascript复制
// 监听文本框的输入,而且只有大于3个长度的时候才会打印
[[self.textField.rac_textSignal filter:^BOOL(NSString * _Nullable value) {
      return value.length > 3;
 }]subscribeNext:^(NSString * _Nullable x) {
        NSLog(@"%@", x);
 }];
UIButton的点击事件
代码语言:javascript复制
 [[self.button rac_signalForControlEvents:UIControlEventTouchUpInside]subscribeNext:^(__kindof UIControl * _Nullable x) {
        NSLog(@"%@", x);
   }];
经典的ReactiveCocoa实现登录

Account

代码语言:javascript复制
#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

代码语言:javascript复制
#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

代码语言:javascript复制
#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

代码语言:javascript复制
#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。按钮点击事件啊。

ReactiveCocoaDemo

0 人点赞