MVVM-ReactiveCocoa

上一篇博文,我们讲解了MVVM框架的相关知识。在这篇博文将使用ReactiveCocoa第三方库实现MVVM架构。

1 引入ReactiveCocoa库

使用CocoaPods引入第三分库ReactiveCocoa。Podfile内相关内容如下:

platform :ios,'9.0'

pod 'ReactiveCocoa','~> 2.3.1'

2 界面设计

在这里我们模拟登录功能

YJViewController类代码如下。

//
// YJViewController.m
// MVVM-ReactiveCocoa
//
// CSDN:http://blog.csdn.net/y550918116j
// GitHub:https://github.com/937447974/Blog
//
// Created by admin on 16/3/7.
// copyright © 2016年 阳君. All rights reserved.
//

#import "YJViewController.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
#import "RACEXTScope.h"
#import "YJviewmodel.h"

@interface YJViewController ()

@property (weak,nonatomic) IBOutlet UITextField *userNameTextField; ///< 用户名
@property (weak,nonatomic) IBOutlet UITextField *passwordTextField; ///< 密码
@property (weak,nonatomic) IBOutlet UIButton *loginButton;          ///< 登录按钮

@property (nonatomic,strong) YJviewmodel *viewmodel; ///< viewmodel对象

@end

@implementation YJViewController

- (void)viewDidLoad {
    [super viewDidLoad];

}

@end

3 MVVM实现

3.1 viewmodel

我们实现一个简单的viewmodel层。

YJviewmodel.h

//
// YJviewmodel.h
// MVVM-ReactiveCocoa
//
// CSDN:http://blog.csdn.net/y550918116j
// GitHub:https://github.com/937447974/Blog
//
// Created by admin on 16/3/7.
// copyright © 2016年 阳君. All rights reserved.
//

#import <Foundation/Foundation.h>

/** viewmodel完全把Model和View进行了分离,主要的程序逻辑在viewmodel里实现*/
@interface YJviewmodel : NSObject

@property (nonatomic,copy) Nsstring *userName; ///< 用户名
@property (nonatomic,copy) Nsstring *password; ///< 密码

@property (nonatomic,copy) Nsstring *title; ///< 标题

/** * 初始化相关数据 * *  @return void */
- (void)initData;

@end

YJviewmodel.m

//
// YJviewmodel.m
// MVVM-ReactiveCocoa
//
// CSDN:http://blog.csdn.net/y550918116j
// GitHub:https://github.com/937447974/Blog
//
// Created by admin on 16/3/7.
// copyright © 2016年 阳君. All rights reserved.
//

#import "YJviewmodel.h"

@implementation YJviewmodel

- (void)initData
{
    NSLog(@"用户名:%@; 密码:%@",self.userName,self.password);
    self.title = @"阳君:937447974";
}

@end

3.2 引入ReactiveCocoa实现MVVM

下面改造YJViewController.m完成和viewmodel层的绑定。

这里实现的需求如下:

  1. 时刻监听用户的输入,当用户输入的用户名和密码大于三位时才能点击登录按钮。
  2. 用户输入错误时输入框显示红色,正确时显示绿色。
  3. 用户输入错误登录按钮不可点,输入正确登录按钮可点。
  4. 用户点击登录按钮1s内重复点击无效。

核心代码实现如下:

- (void)viewDidLoad {
    [super viewDidLoad];
    // 校验用户输入信息
    RACSignal *validUserNameSignal = [self.userNameTextField.rac_textSignal map:^id(Nsstring *value) {
        return @(value.length > 3);
    }];
    RACSignal *validPasswordSignal = [self.passwordTextField.rac_textSignal map:^id(Nsstring *value) {
        return @(value.length > 3);
    }];

    // 根据用户输入信息修改输入框背景色
    RAC(self.userNameTextField,backgroundColor) = [validUserNameSignal map:^id(NSNumber *value) {
        return value.boolValue ? [UIColor greenColor] : [UIColor redColor];
    }];
    RAC(self.passwordTextField,backgroundColor) = [validPasswordSignal map:^id(NSNumber *value) {
        return value.boolValue ? [UIColor greenColor] : [UIColor redColor];
    }];

    // 按钮能否点击
    RAC(self.loginButton,enabled) = [RACSignal combineLatest:@[validUserNameSignal,validPasswordSignal] reduce:^id(NSNumber *usernameValid,NSNumber *passwordValid){
        return @([usernameValid boolValue] && [passwordValid boolValue]);
    }];

    @weakify(self);
    // 1s内禁止重复点击
    [[[[self.loginButton rac_signalForControlEvents:UIControlEventTouchUpInside] map:^id(id value) {
        @strongify(self);
        self.loginButton.enabled = NO;
        [self.viewmodel initData];
        return @(true);
    }] throttle:1] subscribeNext:^(id x) {
        @strongify(self);
        self.loginButton.enabled = YES;
    }];

    // viewmodel绑定
    self.viewmodel = [[YJviewmodel alloc] init];
    RAC(self.viewmodel,userName) = [self.userNameTextField.rac_textSignal map:^id(id value) {
        return value;
    }];
    RAC(self.viewmodel,password) = [self.passwordTextField.rac_textSignal map:^id(id value) {
        return  value;
    }];
    RAC(self,title) = RACObserve(self.viewmodel,title);

}

点击运行即可看见相应效果

Appendix

Sample Code

Swift

Revision History

时间 描述
2016-03-08 博文完成

CSDN:http://blog.csdn.net/y550918116j

GitHub:https://github.com/937447974/Blog

相关文章

react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接...
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc ...