iOS之MVVM架构
来源:互联网 发布:ubuntu chrome 安装 编辑:程序博客网 时间:2024/04/28 04:56
什么是MVVM
model层,API请求的原始数据
view层,视图展示,由viewController来控制
Model层是少不了的了,我们得有东西充当DTO(数据传输对象),当然,用字典也是可以的,编程么,要灵活一些。Model层是比较薄的一层,如果学过Java的小伙伴的话,对JavaBean应该不陌生吧。
ViewModel层,就是View和Model层的粘合剂,他是一个放置用户输入验证逻辑,视图显示逻辑,发起网络请求和其他各种各样的代码的极好的地方。说白了,就是把原来ViewController层的业务逻辑和页面逻辑等剥离出来放到ViewModel层。
View层,就是ViewController层,他的任务就是从ViewModel层获取数据,然后显示。
view-model 一词的确不能充分表达我们的意图. 一个更好的术语可能是 “View Coordinator”(感谢Dave Lee提的这个 “View Coordinator” 术语, 真是个好点子)。你可以认为它就像是电视新闻主播背后的研究人员和作家团队。它从必要的资源(数据库, 网络服务调用, 等)中获取原始数据, 运用逻辑, 并处理成 view (controller) 的展示数据. 它(通常通过属性)暴露给视图控制器需要知道的仅关于显示视图工作的信息(理想地你不会暴漏你的 data-model 对象)。 它还负责对上游数据的修改(比如更新模型/数据库, API POST 调用)。
MVVM是基于胖Model的架构思路建立的,然后在胖Model中拆出两部分:Model和ViewModel。ViewModel本质上算是Model层(因为是胖Model里面分出来的一部分),所以View并不适合直接持有ViewModel,因为ViewModel有可能并不是只服务于特定的一个View,使用更加松散的绑定关系能够降低ViewModel和View之间的耦合度。
ViewController
尽量不涉及业务逻辑,让ViewModel
去做这些事情。ViewController
只是一个中间人,接收View
的事件、调用ViewModel
的方法、响应ViewModel
的变化。ViewModel
不能包含 View,不然就跟 View 产生了耦合,不方便复用和测试。ViewModel
之间可以有依赖。ViewModel
避免过于臃肿,不然维护起来也是个问题。
MVVM 并不复杂,跟 MVC 也是兼容的,只是多了一个 ViewModel 层,但就是这么一个小改动,就能让代码变得更加容易阅读和维护,不妨试一下吧。
怎么实现MVVM呢?接下来我将通过代码来演示一下我的具体实现过程。
model层
在这里我们用JSONModel来解析,比如一个商品列表的model长这样:#import <JSONModel/JSONModel.h>@protocol ProductListModel <NSObject>@end@interface ProductListModel : JSONModel@property (nonatomic, copy) NSString *imgUrl;@property (nonatomic, copy) NSString *productId;@property (nonatomic, copy) NSString *productName;@property (nonatomic, copy) NSString *refPrice;@end
这是我们的数据原型,API返回的数据通过JSONModel解析完成后的原始数据存在这里。
viewModel 层
viewModel层是我们处理业务逻辑的核心层,在这里我们需要发起网络请求(如果网络请求较多,可以抽出来,只在ViewModel里调用)、解析数据、转换数据给前端。
- (void)startLoadProductListWithPage:(NSInteger)page { __weak typeof(self) weakSelf = self; [NetWorkManager GET:self.baseURL parameters:parameters success:^(NSURLSessionDataTask *task, id responseObject) { __strong typeof(weakSelf) strongSelf = weakSelf; ... NSDictionary *resultDic = responseObject[@"rp_result"]; NSError *error = nil; ProductListModel *model = [[ProductListModel alloc] initWithDictionary:resultDic error:&error]; if (error) { ... } [strongSelf calProductLists:model.productlist]; if (strangles.delegate ...) { ... } } failure:^(NSURLSessionDataTask *task, NSError *error) { ... }];}- (void)calProductLists:(NSArray *)productLists { for (NSInteger i = 0; i < productLists.count; ++i) { ProductListModel *model = productLists[i]; ProductListItem *item = [[ProductListItem alloc] init]; item.productId = model.productId; item.productName = model.productName; item.productPrice = [NSString stringWithFormat:@"¥ %@", model.refPrice]; item.productImgURL = [Utils convertToRealUrl:model.imgUrl ofsize:300]; [self.productLists addObject:item]; }}
在viewModel中将API返回的数据解析成model,并将model转化成可供view层直接使用的item,将item交付给前端使用。
经过viewModel转化之后的数据item由viewModel保存,与数据相关的处理都将在viewModel中处理。viewModel返回给view层的接口长这样:@interface ProductListViewModel (CollectionViewDataSource)- (NSInteger)m_numberOfItemsInSection:(NSInteger)section;- (ProductListItem *)m_itemForIndexPath:(NSIndexPath *)indexPath;@end
view层
view层是由viewController控制的。view层只做展示,不做业务处理。view层的数据由viewModel提供。view层看起来是这样的:
@implementation ProductListViewController- (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; [self initial]; [self setupViewModel]; [self setupSubViews]; [self.viewModel startLoadProductListWithPage:_currentPage];}- (void)initial { ... self.currentPage = 1;}- (void)setupViewModel { self.viewModel = [[ProductListViewModel alloc] init]; _viewModel.delegate = self;}- (void)setupSubViews { ... [self setupCollectionView]; ...}- (void)setupCollectionView { ...}#pragma mark - UICollectionView Delegate & Datosource- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return [self.viewModel m_numberOfItemsInSection:section];}- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { ProductListItem *item = [self.viewModel m_itemForIndexPath:indexPath]; ProductListCollectionViewCell *cell = (ProductListCollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:kProductListCollectionViewCellId forIndexPath:indexPath]; [cell setupWithItem:item]; return cell;}
MVVM的缺点
转化过程的成本很大,主要在于:1、数组内容的转化成本较高:数组里面每项都要转化成Item对象,如果Item对象中还有类似数组,就很头疼。
2、转化之后的数据在大部分情况是不能直接被展示的,为了能够被展示,还需要第二次转化。
3、只有在API返回的数据高度标准化时,这些对象原型(Item)的可复用程度才高,否则容易出现类型爆炸,提高维护成本。
4、调试时通过对象原型查看数据内容不如直接通过NSDictionary/NSArray直观。
5、同一API的数据被不同View展示时,难以控制数据转化的代码,它们有可能会散落在任何需要的地方。
针对这些缺点,也提出了相应的解决方法,即用一个类似reformer的对象进行数据过滤,根据不同的reformer对象过滤出不同的数据。
另外,这篇文章说得也很浅显易懂!
- iOS之MVVM架构
- ios 架构设计 MVVM
- iOS架构:MVVM+RAC
- ios MVVM架构设计
- iOS架构 - MVC/MVP/MVVM
- iOS 客户端架构设计 MVVM
- iOS中MVVM的架构设计
- iOS中MVVM的架构设计
- 浅谈iOS中MVVM的架构设计
- iOS中MVVM的架构设计
- iOS 架构模式 - 简述 MVC, MVP, MVVM
- 浅谈iOS中MVVM的架构设计
- iOS开发之 MVVM的架构设计与团队协作的重要性
- iOS开发之浅谈MVVM的架构设计与团队协作
- iOS开发之浅谈MVVM的架构设计与团队协作
- iOS开发之浅谈MVVM的架构设计与团队协作
- Android架构之MVC,MVP与MVVM
- 浅谈Android架构之MVP,MVVM
- c++ 中 this指针的使用
- linux 常用命令
- java集合之LinkedList
- C#实现的系统内存清理
- 二叉树中的最大路径和-LintCode
- iOS之MVVM架构
- linux脚本语言之shell 中的eval
- Tyvj 1728 普通平衡树
- 谈谈对Spring框架的理解
- 从机器学习谈起
- 【Opencv】使用二维特征点(Features2D)和单映射(Homography)寻找已知物体
- POJ 2395 Out of Hay 最小生成树 Kruskal
- Android
- Hadoop是什么?