简介
OC 中MVC和MVVM的争论是一个经久不衰的话题。
MVC是入门;第一次接触MVVM,就非常认同其理念;再后来RAC也学习过,实践过,体验过双向绑定的神奇之处;再后来,小型项目又回归MVC;感觉MVVM像是双刃剑,跟MVC之间大约五五开的样子。
当前的选择
-
整个工程师MVC的;因为RAC对于OC的支持在下降,其重心已经转向Swift;
-
在某些地方,ViewModel还是能够带来便利的,比如表格;本次实践就是这个;
表格实践
界面截图
图片展示部分是横向表格,使用UICollectionView是最方便的
文件夹截图

这里的ViewModel是为cell服务的
基类ViewModel
-
和Model类似,提供一个基类,进行一级继承,能够带来方便;
-
和Model类似,利用YYModel实现<NSCopying, NSCoding>能带来很大的便利;
@interface WGBBaseViewModel : NSObject <NSCopying, NSCoding>
@end
#import "WGBBaseViewModel.h"
#import <YYModel/YYModel.h>
@implementation WGBBaseViewModel
#pragma mark - NSCopying, NSCoding
- (void)encodeWithCoder:(NSCoder *)coder {
[self yy_modelEncodeWithCoder:coder];
}
- (instancetype)initWithCoder:(NSCoder *)coder {
if (self = [super init]) {
[self yy_modelInitWithCoder:coder];
}
return self;
}
- (id)copyWithZone:(NSZone *)zone {
return [self yy_modelCopy];
}
- (NSUInteger)hash {
return [self yy_modelHash];
}
- (BOOL)isEqual:(id)object {
return [self yy_modelIsEqual:object];
}
@end
ViewModel的内容
- 界面显示的内容,这些以属性的方式存在。
@interface WGBNormalCellViewModel : WGBBaseViewModel
#pragma mark - 属性
/// 图片的url
@property (copy, nonatomic, nullable) NSString *urlString;
/// 照片数据(原图数据)
@property (strong, nonatomic, nullable) UIImage *image;
/// 是否是远程图片
@property (assign, nonatomic) BOOL isRemote;
/// 添加图片结点,显示➕图怕
@property (assign, nonatomic) BOOL isAddNode;
@end
这个案例比较简单,主要区分远程图片(urlString),本地图片(image),以及排在最后的添加图片(isAddNode)
- 构造方法,从数据创建。这个一般以构造方法存在。
@interface WGBNormalCellViewModel : WGBBaseViewModel
#pragma mark - 构造方法
/// 创建远程url结点
- (instancetype)initWithUrlString:(NSString *)urlString;
/// 创建本地图片结点
- (instancetype)initWithImage:(UIImage *)image;
/// 创建本地图片结点
- (instancetype)initAddNode;
@end
非常简单,就是提供三种不同结点的构造方法
Cell的定义
- 只需要提供一个通过ViewModel更新界面的方法就可以了
@interface WGBNormalCell.h : UICollectionViewCell
/// 更新界面
- (void)updateWithViewModel:(WGBNormalCellViewModel *)viewModel;
@end
- 界面元素,具体界面设置的方式,隐藏在.m文件中就可以了
#import "WGBNormalCell.h"
@interface WGBNormalCell ()
/// 主图片
@property (weak, nonatomic) IBOutlet UIImageView *mainImageView;
/// 类型图片
@property (weak, nonatomic) IBOutlet UIImageView *typeImageView;
@end
@implementation WGBNormalCell
/// 更新界面
- (void)updateWithViewModel:(WGBNormalCellViewModel *)viewModel {
if (viewModel.isAddNode) {
self.mainImageView.image = [UIImage imageNamed:@"添加图片"];
self.typeImageView.hidden = YES;
return;
}
self.typeImageView.hidden = NO;
if (viewModel.isRemote) {
self.typeImageView.image = [UIImage imageNamed:@"云端图片标志"];
[self.mainImageView yy_setImageWithURL:[NSURL URLWithString:viewModel.urlString] options:YYWebImageOptionProgressive];
} else {
self.typeImageView.image = [UIImage imageNamed:@"相机图片标志"];
self.mainImageView.image = viewModel.waterImage;
}
}
@end
使用
- 字典转模型,从网络接收数据
/// 字典转Model
WGBNormalPhotoModel *model = [WGBNormalPhotoModel instanceWithJSON:response targetClass:[WGBNormalPhotoModel class]];
- 根据Model数据,调用构造方法,创建ViewModel
NSMutableArray<WGBNormalCellViewModel *> *tempArray = [NSMutableArray arrayWithArray:self.nodeArray];
/// 网络结点
if ([WGBArrayUtil isNotEmpty:urlArray]) {
for (NSString *urlString in urlArray) {
WGBNormalCellViewModel *viewModel = [[WGBNormalCellViewModel alloc] initWithUrlString:urlString itemNo:self.itemNo];
[tempArray addObject:viewModel];
}
}
/// 照片结点
if ([WGBArrayUtil isNotEmpty:imageArray]) {
for (UIImage *image in imageArray) {
WGBNormalCellViewModel *viewModel = [[WGBNormalCellViewModel alloc] initWithImage:image itemNo:self.itemNo];
[tempArray addObject:viewModel];
}
}
/// 结点数据源
self.dataSource = [tempArray copy];
/// 更新表格
[self.imageCollectionView reloadData];
- 在表格中动态创建Cell,更新界面
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
WGBNormalCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"WGBNormalCell" forIndexPath:indexPath];
WGBNormalCellViewModel *viewModel = self.dataSource[indexPath.row];
[cell updateWithViewModel:viewModel];
return cell;
}
小结
-
MVVM模式用在表格页面,能够使结构清晰,值得多套一层;
-
如果是代码写View,增加一层ViewModel也是好的。表格跟代码写View情况类似。
-
用故事版,还是直接在ViewController中写业务比较方便,加一层ViewModel反而更繁琐,不如直接用MVC来得简洁
-
如果用RAC,用MVVM架构也是很不错的。反过来也一样,如果用MVVM架构,最好引入RAC这个黑科技
网友评论