MVVM初步心得

最近公司招了一个高级开发,采用的流行的MVVM+RAC+cocopods私有库开发。一开始我一直使用的事MVC的经典模式,也没接触过组件化,在这里先简单说说采用MVVM模式开发的想法。

在这里插入图片描述

MVC:Model View Controller (Massive View controller重量级视图控制器)
从上面可以看到原来MVC模式下Controller的占比,想要未视图控制器瘦身,并且进一步分离事物,MVVM华丽登场。
MVVM:Model View View-Model
1.Model 模型层,或许会也或许不会封装一些额外的业务逻辑工作,我更偏向于单纯的数据模型对象。
2.View 视图本身当然也包含视图控制器本身,和用户互动的都在视图层面。
3.ViewModel
在实际的项目中,会将网络请求模块、数据解析、以及一些业务逻辑处理等都放在这个继承于NSObject类的ViewModel文件中,最终只暴露给View或者Controller一个需要的结果。
一个更好的术语可能是 “View Coordinator”(感谢[Dave Lee](https://twitter.com/kastiglione)提的这个 “View Coordinator” 术语, 真是个好点子). 你可以认为它就像是电视新闻主播背后的研究人员和作家团队. 它从必要的资源(数据库, 网络服务调用, 等)中获取原始数据, 运用逻辑, 并处理成 view (controller) 的展示数据. 它(通常通过属性)暴露给视图控制器需要知道的仅关于显示视图工作的信息(理想地你不会暴漏你的 data-model 对象). 它还负责对上游数据的修改(比如更新模型/数据库, API POST 调用).

对于Model View ViewModel Controller 的引用关系,Contrller、View引用ViewModel, ViewModel引用Model、ViewModel,并且是单向引用(这里的单向引用,我还不是特别明白是不是必须,但至少在结合cocopods私有库开发的时候,因为依赖关系必须单向,所以必须是单向引用,也许也就是因为私有库而限制的这一点)。

一个视图可以对应一个ViewModel,也可以多个视图对应一个ViewModel,也可以一个视图对应多个ViewModel。为了方便代码的阅读性,推荐一个视图对应一个ViewModel以及ViewModel中引用子ViewModel,这样处理起来非常的清晰有条理。

粘贴部分代码看下基本的MVVM 实现列表的基本引用过程:

VC:

#import "TestViewModel.h"
#import "TestCellViewModel.h"
#import "TestModel.h"

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    TestCellViewModel *cellViewModel = self.viewModel.list[indexPath.section];
   TestCell *cell = [tableView dequeueReusableCellWithIdentifier:grayCellIdentifier];
        if (!cell) {
            cell = [[TestCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:grayCellIdentifier];
        }
        [cell renderWithViewModel:cellViewModel];
        return cell;
}

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

ViewModel:
.h

@interface TestViewModel : NSObject
@property (nonatomic, copy, readonly) NSArray *list;
@end

.m:

@interface TestViewModel()
@property (nonatomic, strong) NSMutableArray *mulDataSourceArr;
@end

@implementation TestViewModel
- (instancetype)init {
	if (self = [super init]) {
		[self initialize];
	}
	return self;
}

- (void)initialize {
	//请求网络数据
	//这里才用的RACCommand方式,暂时先不说明
	[self appendModelArray:@"Model解析的数据数组"];
}

#pragma mark - Private Methods

- (void)appendModelArray:(NSArray<TestModel *> *)array {
    for (NSInteger i = 0; i < array.count; i++) {
        TestCellViewModel *itemVM = [[TestCellViewModel alloc] initWithModel:array[i]];
        if (itemVM) {
            [self.mulDataSourceArr addObject:itemVM];
        }
    }
}
- (NSArray *)list {
    return self.mulDataSourceArr.copy;
}
- (NSMutableArray<TestCellViewModel *> *)mulDataSourceArr{
    if (!_mulDataSourceArr) {
        _mulDataSourceArr = [[NSMutableArray<TestCellViewModel *> alloc] initWithCapacity:10];
    }
    return _mulDataSourceArr;
}

@end 

CellViewModel:

.h

#import "TestModel.h"
@interface DYMineRegistrationCellViewModel : NSObject
///
@property (nonatomic, copy, readonly) NSAttributedString *formattedTitle;
@property (nonatomic, copy, readonly) NSString *formattedText;

.m

- (instancetype)initWithModel:(id)model {
    NSAssert([model isKindOfClass:[DYMineRegistrationModel class]], @"model必须为DYMineRegistrationModel类型");
    if (self = [super init]) {
        self.itemModel = model;
    }
    return self;
}
#pragma mark - Getter Methods
- (NSAttributedString *)formattedtitle{
    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@ ",self.itemModel.enregisterShare] attributes:@{NSFontAttributeName: [UIFont fontWithName:@"DINAlternate-Bold" size:15], NSForegroundColorAttributeName: UIColorHex(0x333333)}];
    [attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:@"哈哈哈)" attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:10 weight:UIFontWeightRegular], NSForegroundColorAttributeName: UIColorHex(0xA3A3A3)}]];
    return attributedString.copy;
}

- (NSString *)formattedText {
   return xxx;
}

cell:
.h


#import <UIKit/UIKit.h>

@class TestCellViewModel;
@interface TestCell : UITableViewCell

/**
 渲染数据

 @param viewModel VM
 */
- (void)renderWithViewModel:(TestCellViewModel *)viewModel;

@end

.m

#import "TestCell.h"
#import "TestCellViewModel.h"
@implementation TestCell

- (void)renderWithViewModel:(DYMineRegistrationCellViewModel *)viewModel{
    _viewModel = viewModel;
    self.nameLabel.text = viewModel.formattedTitle;
    self.textLabel.attributedText = viewModel.formattedText;
}
@end

我理解的基本流程如上,希望各位大神多多指点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值