淺談iOS中MVVM的架構設計


  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轉化之后的數據itemviewModel保存,與數據相關的處理都將在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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM