介绍一下MVC和MVVM
这篇文章先,然后结合一个UITableView的实例来进行分析
在这里插一下个人观点,我一直觉得设计模式只是服务于业务场景,其实在绝大多数场景下MVC完全足够,如果说页面过于复杂,我才会去抽离Controller 层的代码,实现逻辑分离。所以在写代码的时候我并不会一开始就用十分复杂的结构,只是在需要扩展的时候才会去重构。因为可能这一业务功能就这么多了,过两个版本这个功能就不需要了,所以我们得根据业务去衡量。
一、MVC
从写代码开始,用的最多的应该就属MVC和单例这两种设计模式了。
1. 什么是MVC?
Model-View-Controller,Model持有数据,View显示与用户交互的界面,而View Controller调解Model和View之间的交互。
**
View:**基本的视图的代码,可以用xib或者storyboard,或者手写代码。实际开发中一般会自定义出一个View,并设置好内部的UILabel,UIButton等组件。
**Model:**实体对象,最基本的原子单位
**Controller:**Controller是app的“胶水代码”:协调模型和视图之间的所有交互。控制器负责管理他们所拥有的视 图的视图层次结构,还要响应视图的loading、appearing、disappearing等等
2. MVC缺点
厚重的View Controller很难维护(由于其庞大的规模),包含几十个属性,使他们的状态难以管理;遵循许多协议(protocol),导致协议的响应代码和controller的逻辑代码混淆在一起。
3. 快速优化,增加中间层
**Control:**用来做网络交互和数据存储用,核心点在于数据的管理
**Component:**自定义的组件
这种层可以根据业务的存在继续细分,这里不作过多解释。
二、MVVM
**
ViewModel:**MVVM就是一个经过优化的MVC,这意味着它可以兼容,也本质上还是一个MVC结构.
是一个放置用户输入验证逻辑,视图显示逻辑,由于展示逻辑(presentation logic)放在了ViewModel中(比如model的值映射到一个格式化的字符串),视图控制器本身就会不再臃肿。
理解成Controller和Model之间的一座桥梁即可
三、TableView实战
这里着重介绍一下数据源TableViewDataSource和QQViewModel
###1.QQViewModel:
.h文件
#import <Foundation/Foundation.h>
@class QQModel;
@interface QQViewModel : NSObject
- (instancetype)initWithQQViewModel:(QQModel *)qqModel;
@property (nonatomic, strong) QQModel *qqModel;
@property(copy,nonatomic) NSString *content;
@end
.m文件
#import "QQViewModel.h"
#import "QQModel.h"
@implementation QQViewModel
- (instancetype)initWithQQViewModel:(QQModel *)qqModel
{
if (self = [super init]){
self.qqModel = qqModel;
self.content = [NSString stringWithFormat:@"%@View",qqModel.title];
}
return self;
}
@end
如上述所示,QQModel是一个最基本的原子单位,QQViewModel是包括了QQModel,以及View所需要展示的一些字段,我们可以将这些字段的逻辑都封装在QQViewModel中,减少Controller的臃肿。View层只要直接拿到ViewModel即可,不用Controller在转哦概念图做转换。上述的content就是我们需要的字段,其他可根据View自行扩充。
2. TableViewDataSource:
在请求到网络数据后,刷新数据源
/* 设置表格的数据源 */
- (void)setupTableViewDataSource
{
TableViewCellConfigureBlock configureCell = ^(QQTableCell *cell, id item){
[cell configureForData:item];
};
_qqDataSource = [[QQDataSource alloc] initWithItems:_publicModelArray
cellIdentifier:QQCELLIDENDIFIFY
configureCellBlock:configureCell];
_qqTableView.dataSource = _qqDataSource;
}
这是QQDataSource的核心就是通过block将建立起一个直接映射到Cell上的作用,起到一个数据透传的作用。动态地通过item去设置cell的值。在QQDataSource中的处理:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"indexPath.row,indexPath.section:(%ld,%ld)",indexPath.row,indexPath.section);
QQTableCell *cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentifier forIndexPath:indexPath];
id item = [self itemAtIndexPath:indexPath];
self.configureCellBlock(cell,item);
return cell;
}
小结:
在前几年的工作中,每次写新功能大概就是这个套路,先新建几个文件夹,然后分好上述的几层。再深层次优化就是做一些公共组件之类的,设置一些父类,抽出公共代码,比如公共的网络连接库,SuperController之类。
demo下载链接:
参考链接:
1.scaling-isomorphic-javascript-code
2.github.com/lizelu/MVVM
3.objccn.io/issue-13-1/