一個快速開發框架:MVVMFramework-Swift

jopen 9年前發布 | 33K 次閱讀 Apple Swift開發 MVVMFramework-Swift

MVVMFramework-Swift

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

再看了幾篇博客后,總結整理下一個快速開發MVVM框架,分離控制器代碼,降低代碼耦合

終于再也不用為ViewController中一坨坨tableView和collectionView的煩人代碼憂慮了

代碼加入了cell自適應高度代碼,配合MJExtension,MJExtension,AFNetworking等常用開發框架使用更佳,主要用于分離控制器中的代碼,降低代碼耦合程度,可以根據自己使用習慣調整代碼。歡迎來噴,提issues。

思維流程圖示

image

現在的工程代碼結構

image

模塊構建


結構分析


代碼分析

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

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!