小記:iOS 中通常對於 view 不依賴 model 的的兩種代碼書寫形式

一. 前言

  • 對於在 MVC 的定義中,view 層是不引用 model 層,view 和 model 是不相往來的編程

  • 通常開發中,咱們都寫過 在自定義 view 中增長一個 model 的屬性,外接直接傳個 model 來,在 view 中 model 的 set 方法裏對 view 的控件賦值的代碼,例如在自定義 UITableViewCell 時用的不少,此時 view 是直接引用了 modelatom

  • 基於封裝的思想,咱們須要竟可能的複用咱們的代碼,複用咱們的 view,這時咱們須要進行解耦,不依賴於某個特殊的 model。另外,若是對於很特殊的 view,整個項目中沒有什麼重用的,能夠按以前狀況處理code

  • 本文簡要介紹本身經常使用的兩種寫法來解耦 view 和 model,使之更符合 MVC 的定義對象

二.定義 ViewModel 對象及 ViewModelType (協議) 的形式

  • 說明
    • 將 view 中全部控件須要的數據依次列出
    • 定義 ViewModelType 一種協議,定義協議方法 ,旨在經過協議方法,返回 view 須要的數據
    • view 中控件賦值,須要外接傳入遵照 ViewModelType 協議的 ViewModel,在 ViewModel 的 set 方法裏進行控件賦值
    • 該 ViewModel 的建立是依賴具體的 model 的,須要遵照 ViewModelType 協議
    • view 和 ViewModelType 爲一總體,經過更換不一樣的 ViewModel 來達到重用。更換不一樣 ViewModel,也至關於更換了數據 model。
  • 示例
    • 如一個 cell (有大標題,幾個子標題和標題對應的內容,狀態,圖片等)圖片

      @interface LXReservationCell : UITableViewCell
      
      @property (nonatomic, weak) id<LXReservationCellViewModelType> viewModel;
      
      @end
    • LXReservationCellViewModelType 協議開發

      @protocol LXReservationCellViewModelType <NSObject>
      
      // 標題
      @property (nonatomic, copy, readonly) NSString *title;
      // 第一個子標題
      @property (nonatomic, copy, readonly) NSString *firstItemTitle;
      // 第一個子標題對應的內容
      @property (nonatomic, copy, readonly) NSString *firstItemContent;
      
      @end
    • LXReservationCellViewModel 中it

      #import <Foundation/Foundation.h>
      
      @class LXReservationItem;
      
      @interface LXReservationCellViewModel : NSObject
      
      - (instancetype)initWithItem:(LXReservationItem *)item;
      
      @end
      @interface LXReservationCellViewModel () <LXReservationCellViewModelType>
      // 標題
      @property (nonatomic, copy) NSString *title;
      // 第一個子標題
      @property (nonatomic, copy) NSString *firstItemTitle;
      // 第一個子標題對應的內容
      @property (nonatomic, copy) NSString *firstItemContent;
      @end
      @implementation LXReservationCellViewModel
      
      - (instancetype)initWithItem:(LXReservationItem *)item {
          if (self = [super init]) {
              self.title = item.title;
              self.firstItemTitle = item.orderCategory;
              self.firstItemContent = item.orderdate;
      
          }
          return self;
      
      }

3、定義 view 對應的 config,使用鏈式編程的形式進行對 view 控件賦值

  • 說明
    • 將 view 中全部控件須要的數據依次列出
    • 定義一個 config 對象,使用鏈式編程的形式進行獲取 view 須要的各類數據,在 config 中弱引用 view,把各類數據在賦值給 view
    • view 中須要定義一個配置數據的方法,方法的參數是個 block,block 傳一個 config 對象給外界使用
    • view 和 config 爲一總體,並不引用 model,所以脫離的 model 的限制,具備重用性
  • 示例
    • 如一個簡單的展現標題、內容,還有一個按鈕的 viewio

      #import <UIKit/UIKit.h>
      
      @class LXIntroduceViewConfig;
      
      @interface LXIntroduceView : UIView
      // 標題
      @property (nonatomic, copy) NSString *title;
      // 內容
      @property (nonatomic, copy) NSString *content;
      // 按鈕標題
      @property (nonatomic, copy) NSString *btnTitle;
      
      // 配置 view 對應的數據的方法
      - (void)lx_makeWithConfig:(void(^)(LXIntroduceViewConfig *config))block;
      - (void)lx_makeWithConfig:(void (^)(LXIntroduceViewConfig *))block {
        LXIntroduceViewConfig *config = [[LXIntroduceViewConfig alloc]initWithIntroduceView:self];
        !block? :  block(config);
      }
    • LXIntroduceViewConfig.hclass

      #import <Foundation/Foundation.h>
      
      @class LXIntroduceView;
      
      @interface LXIntroduceViewConfig : NSObject
      
      - (instancetype)initWithIntroduceView:(LXIntroduceView *)introduceView;
      // 設置標題
      - (LXIntroduceViewConfig *(^)(NSString *))setupTitle;
      // 設置要顯示的內容
      - (LXIntroduceViewConfig *(^)(NSString *))setupContent;
      // 設置按鈕的標題
      - (LXIntroduceViewConfig *(^)(NSString *))setupBtnTitle;
      
      @end
    • LXIntroduceViewConfig.mtest

      @interface LXIntroduceViewConfig ()
      // 弱引用 view 
      @property (nonatomic, weak) LXIntroduceView *introduceView;
      @end
      
      @implementation LXIntroduceViewConfig
      // init
      - (instancetype)initWithIntroduceView:(LXIntroduceView *)introduceView {
          if (self = [super init]) {
              self.introduceView = introduceView;
          }
          return self;    
      }
      // 把標題傳給 view,view 中 set 方法接收
      - (LXIntroduceViewConfig *(^)(NSString *))setupTitle {
          return ^(NSString *tmp) {
              self.introduceView.title = tmp;
              return self;
          };
      }
      // 把內容傳給 view,view 中 set 方法接收
      - (LXIntroduceViewConfig *(^)(NSString *))setupContent {
          return ^(NSString *tmp) {
              self.introduceView.content = tmp;
              return self;
          };
      }
      // 把按鈕標題傳給 view
      - (LXIntroduceViewConfig *(^)(NSString *))setupBtnTitle {
          return ^(NSString *tmp) {
              self.introduceView.btnTitle = tmp;
              return self;
          };
      }
      @end
    • 外界使用

      LXIntroduceView *introduceView = [[LXIntroduceView alloc]init];
      [introduceView lx_makeWithConfig:^(LXIntroduceViewConfig *config) {
          config
          .setupTitle(self.resultItem.title)
          .setupContent(self.resultItem.content) 
          .setupBtnTitle(@"test");
      }];

四. 結尾

  • 一點一滴,僅此記錄。
相關文章
相關標籤/搜索