一个快速开发框架:MVVMFramework-Swift

jopen 9年前

MVVMFramework-Swift

OC版本地址:https://github.com/lovemo/MVVMFramework

再看了几篇博客后,总结整理下一个快速开发MVVM框架,分离控制器代码,降低代码耦合

终于再也不用为ViewController中一坨坨tableView和collectionView的烦人代码忧虑了

代码加入了cell自适应高度代码,配合MJExtension,MJExtension,AFNetworking等常用开发框架使用更佳,主要用于分离控制器中的代码,降低代码耦合程度,可以根据自己使用习惯调整代码。欢迎来喷,提issues。

思维流程图示

image

现在的工程代码结构

image

模块构建

  • 功能模块中的类集合 </li> </ul>

    结构分析

    • Handler中BQViewModel抽象出的类集合 </li> </ul>

      代码分析

      BaseViewModel中代码实现

      // ViewModel基类  class BQBaseViewModel: NSObject {      weak var viewController: UIViewController?      /**       *  懒加载存放请求到的数据数组       */      lazy var dataArrayList:NSMutableArray = {          return NSMutableArray()      }()      required override init() {        }        /**       *  返回指定indexPath的item       */      func modelAtIndexPath(indexPath: NSIndexPath) -> AnyObject? {          return nil      }      /**       *  显示多少组 (当tableView为Group类型时设置可用)       */      func numberOfSections() -> Int {          return 1      }      /**       *  每组中显示多少行 (用于tableView)       */      func numberOfRowsInSection(section: Int) -> Int {          return 0      }      /**       *  每组中显示多少个 (用于collectionView)       */      func numberOfItemsInSection(section: Int) -> Int {          return 0      }      /**       *  分离加载首页控制器内容 (内部使用)       */      func getDataList(url: String!, params: [NSObject : AnyObject]!, success: (([AnyObject]!) -> Void)!, failure: ((NSError!) -> Void)!) {        }      /**       *  用来判断是否加载成功,方便外部根据不同需求处理 (外部使用)       */      func getDataListSuccess(success: Void -> Void, failure: Void -> Void) {        }  }  extension BQBaseViewModel {      class func modelWithViewController(viewController: UIViewController) -> Self? {          let model = self.init()          model.viewController = viewController          return model      }  }

      XTableDataDelegate中部分代码实现

      /**   *  配置UITableViewCell的内容Block   */  typealias TableViewCellConfigureBlock = (NSIndexPath, AnyObject, UITableViewCell) -> Void  /**   *  选中UITableViewCell的Block   */  typealias DidSelectTableCellBlock = (NSIndexPath, AnyObject) -> Void  /**   *  设置UITableViewCell高度的Block (已集成UITableView+FDTemplateLayoutCell,现在创建的cell自动计算高度)   */  typealias CellHeightBlock = (NSIndexPath, AnyObject) -> CGFloat

      XTCollectionDataDeleagte中部分代码实现

      /**   *  配置UICollectionViewCell的内容Block   */  typealias CollectionViewCellConfigureBlock = (NSIndexPath, AnyObject, UICollectionViewCell) -> Void  /**   *  选中UICollectionViewCell的Block   */  typealias DidSelectCollectionCellBlock = (NSIndexPath, AnyObject) -> Void  /**   *  设置UICollectionViewCell大小的Block   */  typealias CellItemSize = ( ) -> CGSize  /**   *  获取UICollectionViewCell间隔Margin的Block   */  typealias CellItemMargin = ( ) -> UIEdgeInsets

      现在的创建tableView代码

      由于用到了UITableView+FDTemplateLayoutCell,现在创建的cell自动计算高度,满足日常开发需求。

      /**      *  tableView的一些初始化工作      */      func setupTableView() {          self.table.separatorStyle = .None;            // 配置tableView的每个cell          let configureCell: TableViewCellConfigureBlock = {(indexPath, obj, cell) -> Void in              cell.configure(cell, customObj: obj, indexPath: indexPath)          }            // 设置点击tableView的每个cell做的一些工作          let selectedBlock: DidSelectTableCellBlock  = { [weak self] (indexPath, item) -> Void in              if let strongSelf = self {                  let sb = UIStoryboard(name: "Main", bundle: nil)                  let vc = sb.instantiateViewControllerWithIdentifier("ViewController2ID")                  strongSelf.presentViewController(vc, animated: true, completion: nil)                  print("click row : \((indexPath.row))")              }          }            // 将上述block设置给tableHander          self.tableHander = XTableDataDelegate.init(viewModel: BQViewModel(),                                                     cellIdentifier: MyCellIdentifier,                                                     configureCellBlock: configureCell,                                                     didSelectBlock: selectedBlock)          // 设置UITableView的delegate和dataSourse为collectionHander          self.tableHander?.handleTableViewDatasourceAndDelegate(self.table)        }

      现在的创建collectionView代码

      /**      *  collectionView的一些初始化工作      */      func setupCollectionView()      {          // 配置collectionView的每个item          let configureCell: CollectionViewCellConfigureBlock  = {(indexPath,  obj, cell) -> Void in              cell.configure(cell, customObj: obj, indexPath: indexPath)          }          // 设置点击collectionView的每个item做的一些工作          let selectedBlock: DidSelectCollectionCellBlock  = {(indexPath, item) -> Void in              print("click row : \((indexPath.row))")             self.dismissViewControllerAnimated(true, completion: nil)          } ;          // 配置collectionView的每个item的size          let cellItemSizeBlock: CellItemSize  = {              return CGSizeMake(110, 120)          };          // 配置collectionView的每个item的margin          let cellItemMarginBlock: CellItemMargin  = {              return UIEdgeInsetsMake(0, 20, 0, 20)          };          // 将上述block设置给collectionHander          self.collectionHander = XTCollectionDataDelegate.init(viewModel: BQViewModel2(),                                                                cellIdentifier: MyCellIdentifier2,                                                                collectionViewLayout: UICollectionViewFlowLayout(), // 可以使用自定义的UICollectionViewLayout                                                                                                                                                   configureCellBlock: configureCell,                                                                cellItemSizeBlock: cellItemSizeBlock,                                                                cellItemMarginBlock: cellItemMarginBlock,                                                                didSelectBlock: selectedBlock)          // 设置UICollectionView的delegate和dataSourse为collectionHander          self.collectionHander?.handleCollectionViewDatasourceAndDelegate(self.collectionView)        }

      demo效果

      • 只需实现加载请求以及配置自定义cell和上述代码,就能轻松实现以下效果,最重要的是代码解耦。

      image

      使用方法

      • 导入BQViewModel文件,然后在模块代码中新建ViewModel子类,继承BQBaseViewModel类型,实现加载数据等方法。
      • 在ViewController中,初始化tableView或者collectionView,根据需要实现block代码,利用XTableDataDelegate或者XTCollectionDat aDelegate的初始化方法将block代码和自己实现的ViewModel类型传递到内部,将会自动根据传入的内容去展现数据。
      • 利用xib自定义cell,在 override func configure(cell: UITableViewCell, customObj obj: AnyObject, indexPath: NSIndexPath)方法中根据模型Model内容配置cell展示的数据。

      期待

      • 如果在使用过程中遇到BUG,希望你能Issues我,谢谢(或者尝试下载最新的代码看看BUG修复没有)
      • 如果在使用过程中发现功能不够用,希望你能Issues我,我非常想为这个框架增加更多好用的功能,谢谢

      推荐-几篇不错的MVVM学习文章

      项目地址: https://github.com/lovemo/MVVMFramework-Swift