MVVM
就是在MVC
的基礎上分離出業務處理的邏輯到viewModel
層。
M: Model層是API請求的原始數據,充當DTO(數據傳輸對象),當然,用字典也是可以的,編程么,要靈活一些。Model層是比較薄的一層。
V: View層,視圖展示,由viewController
來控制,他的任務就是從ViewModel層獲取數據,然后顯示。
VM: ViewModel層負責業務處理和數據轉化,就是View和Model層的粘合劑,他是一個放置用戶輸入驗證邏輯,視圖顯示邏輯,發起網絡請求和其他各種各樣的代碼的極好的地方。說白了,就是把原來ViewController層的業務邏輯和頁面邏輯等剝離出來放到ViewModel層。
簡單來說,就是API請求完數據,解析成model
,之后在viewModel
中轉化成能夠直接被視圖層使用的數據,交付給前端。
model層
我們先從model層開始,在這里我們用JSONModel來解析,比如一個商品列表的model長這樣:
這是我們的數據原型,API返回的數據通過JSONModel解析完成后的原始數據存在這里。
#import <JSONModel/JSONModel.h> @protocol LVMProductListModel <NSObject> @end // productList @interface LVMProductListModel : JSONModel @property (nonatomic, copy) NSString *imgUrl; @property (nonatomic, copy) NSString *productId; @property (nonatomic, copy) NSString *productName; @property (nonatomic, copy) NSString *refPrice; @end
viewModel 層
viewModel層是我們處理業務邏輯的核心層,在這里我們需要發起網絡請求(如果網絡請求較多,可以抽出來,只在ViewModel里調用)、解析數據、轉換數據給前端。
#pragma mark - Public Methods - (void)lvm_startLoadProductListWithPage:(NSInteger)page { __weak typeof(self) weakSelf = self; [NetWorkManager GET:self.lvm_baseURL parameters:parameters success:^(NSURLSessionDataTask *task, id responseObject) { __strong typeof(weakSelf) strongSelf = weakSelf; ... NSDictionary *resultDic = responseObject[@"rp_result"]; NSError *error = nil; LVMProductListModel *model = [[LVMProductListModel alloc] initWithDictionary:resultDic error:&error]; if (error) { ... } [strongSelf _lvm_calProductLists:model.productlist]; if (strangles.delegate ...) { ... } } failure:^(NSURLSessionDataTask *task, NSError *error) { ... }]; } - (void)_lvm_calProductLists:(NSArray *)productLists{ for (NSInteger i = 0; i < productLists.count; ++i) { LVMProductListModel *model = productLists[i]; LVMProductListItem *item = [[LVMProductListItem alloc] init]; item.lvm_productId = model.productId; item.lvm_productName = model.productName; item.lvm_productPrice = [NSString stringWithFormat:@"¥ %@", model.refPrice]; item.lvm_productImgURL = [Utils convertToRealUrl:model.imgUrl ofsize:300]; [self.lvm_productLists addObject:item]; } }
在viewModel
中將API返回的數據解析成model
,並將model
轉化成可供view
層直接使用的item
,將item
交付給前端使用。
經過viewModel
轉化之后的數據item
由viewModel
保存,與數據相關的處理都將在viewModel
中處理。viewModel
返回給view
層的接口長這樣:
@interface LVMProductListViewModel (CollectionViewDataSource) - (NSInteger)lvm_numberOfItemsInSection:(NSInteger)section; - (LVMProductListItem *)lvm_itemForIndexPath:(NSIndexPath *)indexPath; @end
view層
view
層是由viewController
控制的。view
層只做展示,不做業務處理。view
層的數據由viewModel
提供。view
層看起來是這樣的:
@implementation LVMProductListViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; [self _lvm_initial]; [self _lvm_setupViewModel]; [self _lvm_setupSubViews]; [self.lvm_viewModel lvm_startLoadProductListWithPage:_lvm_currentPage]; } - (void)_lvm_initial { ... self.lvm_currentPage = 1; } - (void)_lvm_setupViewModel { self.lvm_viewModel = [[LVMProductListViewModel alloc] init]; _lvm_viewModel.lvm_delegate = self; } #pragma mark - Subviews - - (void)_lvm_setupSubViews { ... [self _lvm_setupCollectionView]; ... } - (void)_lvm_setupCollectionView { ... } #pragma mark - UICollectionView Delegate & Datosource - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return [self.lvm_viewModel lvm_numberOfItemsInSection:section]; } - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { LVMProductListItem *item = [self.lvm_viewModel lvm_itemForIndexPath:indexPath]; LVMProductListCollectionViewCell *cell = (LVMProductListCollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:kLVMProductListCollectionViewCellId forIndexPath:indexPath]; [cell lvm_setupWithItem:item]; return cell; }