美文网首页
MVVM模式示例代码

MVVM模式示例代码

作者: 小苗晓雪 | 来源:发表于2018-08-27 09:44 被阅读168次
文件示例图

viewModel作为连接view与model之间的桥梁 , view与model互不相通!
在控制器中先通过model与viewModel互相绑定好 , 然后将绑定好了model的viewMode对象再去跟view进行绑定!
从而使viewModel达成了view和model之间桥梁的作用!~

MVVMViewCtrl.h

#import <UIKit/UIKit.h>

@interface MVVMViewCtrl : UIViewController

@end

MVVMViewCtrl.m

// MVVM --> model view viewModel 三个文件

#import "MVVMViewCtrl.h"
#import "MVVMPaper.h"       // model
#import "MVVMView.h"        // view
#import "MVVMViewModel.h"   // viewModel

@interface MVVMViewCtrl ()

@property (nonatomic, strong) MVVMPaper *paper;
@property (nonatomic, strong) MVVMView *mvvmView;
@property (nonatomic, strong) MVVMViewModel *viewModel;

@end

@implementation MVVMViewCtrl

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor lightGrayColor];
    // mvvmView:
    self.mvvmView.frame = self.view.bounds;
    [self.view addSubview:self.mvvmView];
    
    // view --> viewModel --> model
    // view <-- viewModel <-- model
    // 双向绑定:
    // 控制器的代码非常简单 , view的布局 , viewModel 与 model 的定制 , view 与 viewModel 之间的定制:
    // 保证view与model彼此之间不互通~
    
    
    // mvvmModel:
    // 给一个初始值"line 0".
    self.paper.contents = @"line 0";
    
    // mvvmViewModel:
    // 所以这里应该先赋值模型 , 让viewModel与model进行绑定:
    [self.viewModel setWithModel:self.paper];
    // 然后再让view与viewModel进行绑定 , 此时的 viewModel 已经是 与model 进行绑定完成之后的viewModel了!
    [self.mvvmView setWithViewModel:self.viewModel];
}


#pragma mark - getter方法
- (MVVMPaper *)paper
{
    if(!_paper)
    {
        _paper = [[MVVMPaper alloc] init];
    }
    return _paper;
}

- (MVVMView *)mvvmView
{
    if(!_mvvmView)
    {
        _mvvmView = [[MVVMView alloc] init];
    }
    return _mvvmView;
}

- (MVVMViewModel *)viewModel
{
    if(!_viewModel)
    {
        _viewModel = [[MVVMViewModel alloc] init];
    }
    return _viewModel;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    
}

@end

MVVMView.h

#import <UIKit/UIKit.h>

// view里添加了viewModel:
#import "MVVMViewModel.h"

@interface MVVMView : UIView

// view监听viewModel中的contentString属性:
- (void)setWithViewModel:(MVVMViewModel *)viewModel;

@end

MVVMView.m

#import "MVVMView.h"
#import "FBKVOController.h"
#import "NSObject+FBKVOController.h"

@interface MVVMView ()

@property (nonatomic, strong) UILabel *contentsLabel;
@property (nonatomic, strong) UIButton *button;
@property (nonatomic, strong) MVVMViewModel *viewModel;

@end

@implementation MVVMView

- (instancetype)init
{
    self = [super init];
    if (self)
    {
        [self addSubview:self.contentsLabel];
        [self addSubview:self.button];
    }
    return self;
}


// 这里是 view 与 viewModel 进行动态绑定的过程 , 让视图作为属性的监听器监听viewModel中的 contentString 属性 , 一旦 contentString 的值有改变 , 就会触发回调 , 这里的block回调中的 change 参数就会有新值 , 把新值赋值给视图中 label 的 text 属性:
- (void)setWithViewModel:(MVVMViewModel *)viewModel
{
    // 要一个 初始值 和 改变之后的 新值:
    [self.KVOController observe:viewModel
                         keyPath:@"contentString"
                         options: NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
                           block:^(id  _Nullable observer,
                                  id  _Nonnull object,
                                  NSDictionary<NSKeyValueChangeKey , id> * _Nonnull change)
    {
        self.contentsLabel.text = change[NSKeyValueChangeNewKey];
    }];
    // 这里再把赋值过来的viewModel实参传递给实例变量 , 用来作为传递点击事件的参数
    self.viewModel = viewModel;
}



#pragma mark - 按钮的点击事件
- (void)buttonClicked:(UIButton *)button
{
    // 把所有的业务逻辑相关代码都传递到viewModel中:
    [self.viewModel onPrintClick];
}


- (MVVMViewModel *)viewModel
{
    if(!_viewModel)
    {
        _viewModel = [[MVVMViewModel alloc] init];
    }
    return _viewModel;
}

- (UIButton *)button
{
    if(!_button)
    {
        _button = [UIButton buttonWithType:UIButtonTypeCustom];
        [_button setTitle:@"print" forState:UIControlStateNormal];
        [_button setFrame:CGRectMake(0, 200, 100, 100)];
        _button.layer.cornerRadius = 5;
        _button.layer.masksToBounds = YES;
        _button.backgroundColor = [UIColor redColor];
        [_button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        _button.backgroundColor = [UIColor redColor];
        [_button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
    }
    return _button;
}

- (UILabel *)contentsLabel
{
    if(!_contentsLabel)
    {
        _contentsLabel = [[UILabel alloc] init];
        _contentsLabel.frame = CGRectMake(100, 100, 100, 30);
        _contentsLabel.font = [UIFont systemFontOfSize:20.0f];
        _contentsLabel.textColor = [UIColor blackColor];
        
    }
    return _contentsLabel;
}

@end

MVVMViewModel.h

#import <Foundation/Foundation.h>
// viewModel是中间的桥梁 , 它连接着view与model , view和model彼此之间是不互通的!
// viewModel中印入model:
#import "MVVMPaper.h"

@interface MVVMViewModel : NSObject

@property (nonatomic, copy) NSString *contentString;
// 设置模型:
- (void)setWithModel:(MVVMPaper *)paper;

// view传递过来的点击事件:
- (void)onPrintClick;

@end

MVVMViewModel.m

#import "MVVMViewModel.h"
#import "FBKVOController.h"

@interface MVVMViewModel ()

@property (nonatomic, strong) MVVMPaper *paper;

@end


@implementation MVVMViewModel

// MVVM的核心: 通过 KVO 的方法将viewModel与view进行 "绑定";
// 绑定的方法通过Facebook开源库 FBKVO

- (instancetype)init
{
    self = [super init];
    if (self)
    {
        self.paper = [[MVVMPaper alloc] init];
    }
    return self;
}

// 传递模型实参给模型属性: , 让模型里的contents字段赋值给viewModel中的 contentString 字段 , 这里就完成了属性之间的关联:
// 让模型与viewModel一一关联 , 之后的视图与model之间的关联都变成了视图与viewModel之间的关联了!
- (void)setWithModel:(MVVMPaper *)paper
{
    self.paper = paper;
    self.contentString = paper.contents;
}



// 点击事件的回调:
- (void)onPrintClick
{
    int randomColor = arc4random() % 10;
    self.paper.contents = [NSString stringWithFormat:@"line %d" , (randomColor + 1)];
    // 这里 contentString 字段改变了 , viewModel中的监听器就会监听到这里的改变 , 从而通过contentString 获取的新值赋值给view的label的text属性:
    self.contentString = self.paper.contents;
}

@end

MVVMPaper.h

// MVVM中的 model 模型文件:

#import <Foundation/Foundation.h>

@interface MVVMPaper : NSObject

@property (nonatomic, copy) NSString *contents;

@end

MVVMPaper.m

#import "MVVMPaper.h"

@implementation MVVMPaper

@end

愿编程让这个世界更美好

相关文章

网友评论

      本文标题:MVVM模式示例代码

      本文链接:https://www.haomeiwen.com/subject/fehziftx.html