Swift3.0 Controller 다이어트

5457 단어

연유


iOS 개발, 우리가 자주 사용하는 구성 요소인 UItableView, UICollectionView는 에이전트를 통해 데이터의 로드를 실현한다. 만약에 우리가 UIViewController에서 에이전트를 의뢰하면 코드의 군더더기를 초래할 수 있다. 또한 Controller가 너무 커서 코드의 Objective-C를 읽을 때 MVVM 프레임워크를 통해 Controller의 다이어트를 실현한다.그러나 여전히 많은 불필요한 코드가 존재할 것이다. Swift 시대에 우리는 MVVM을 바탕으로 Controller의 다이어트를 더욱 잘 실현하고 불필요한 코드를 줄일 수 있다.
구체적인 실현 방식은 MGTV-Swift를 참고하면 좋을 것 같습니다.

이루어지다


ViewModelProtocol

  • 일반적인 프로토콜을 정의하는데 주로 Collection ViewMode와 Table ViewModel
  • 에 사용된다.
    protocol ViewModelProtocol {
        associatedtype DataType //    TableView,CollectionView     
        
        var datas: [[DataType]] { get set } //         ,    ,    section   
        
        associatedtype ViewType //  View   ,   UICollectionView,UITableView
        associatedtype CellType //  Cell   ,   UITableViewCell,UICollectionViewCell
        
        func cellConfig(_ view: ViewType, datas: [[DataType]], indexPath: IndexPath) -> CellType //    ,    cell
    }
    
  • 프로토콜에 Identifier가 전시할 cell을 가져오는 것을 정의하지 않았고,cell의 획득 부분은 외부에 제공하여 여러 종류의 cell 전시에 더욱 유연하게 적용할 수 있다
  • CollectionViewModel

  • typealias를 통해 UICollectionView의 프로토콜을 재정의typealias CollectionViewProtocol = UICollectionViewDelegate & UICollectionViewDataSource & UICollectionViewDelegateFlowLayout
  • extension이 할 수 없는 일부 제한 때문에 일반적인 Collection View 모델은 OOP 방식으로 실현
  • class CollectionViewModel: NSObject, ViewModelProtocol, CollectionViewProtocol {
    
        typealias DataType = T
        typealias ViewType = UICollectionView
        typealias CellType = UICollectionViewCell
        
        var datas: [[T]] = []
        //              UICollectionViewCell
        func cellConfig(_ view: UICollectionView, datas: [[T]], indexPath: IndexPath) -> UICollectionViewCell {
            return UICollectionViewCell()
        }
        //               ,    Cell   
        var minimumLineSpacing: CGFloat { return 0 }
        var minimumInteritemSpacing: CGFloat { return 0 }
        var insetForSection: UIEdgeInsets { return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) }
        var itemSize: CGSize { return CGSize(width: 0, height: 0) }
        
        init(_ collectionDatas: [[T]]) {
            datas = collectionDatas
            super.init()
        }
        
        //MARK: - UICollectionView DataSource
        func numberOfSections(in collectionView: UICollectionView) -> Int {
            return datas.count
        }
        func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            return datas[section].count
        }
        
        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            return cellConfig(collectionView, datas: datas, indexPath: indexPath)
        }
        
        //MARK: UICollectionView DelegateFlowlayout
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
            //   page  
            let itemSizeWith = itemSize.width == 0 ? collectionView.bounds.size.width : itemSize.width
            let itemSizeHeight = itemSize.height == 0 ? collectionView.bounds.size.height : itemSize.height
            return CGSize(width: itemSizeWith, height: itemSizeHeight)
        }
        
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
            return insetForSection
        }
        
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
            return minimumLineSpacing
        }
        
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
            return minimumInteritemSpacing
        }
    }
    

    TableViewModel

  • typealias를 통해 UItableView의 프로토콜을 재정의typealias TableViewProtocol = UITableViewDelegate & UITableViewDataSource
  • class TableViewModel: NSObject, ViewModelProtocol, TableViewProtocol {
        typealias DataType = T
        
        typealias ViewType = UITableView
        typealias CellType = UITableViewCell
        
        var datas: [[T]] = []
        
        func cellConfig(_ view: UITableView, datas: [[T]], indexPath: IndexPath) -> UITableViewCell {
            return UITableViewCell()
        }
        
        func caculateHeight(_ indexPath: IndexPath) -> CGFloat {
            return 0
        }
        
        var cellHeight: CGFloat = -1
        
        init(_ tableDatas: [[T]]) {
            datas = tableDatas
            super.init()
        }
        
        //MARK: - UITableViewDelegate
        func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
            guard cellHeight > 0 else {
                return caculateHeight(indexPath)
            }
            return cellHeight
        }
        
        //MARK: - UITableViewDataSource
        func numberOfSections(in tableView: UITableView) -> Int {
            return datas.count
        }
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return datas[section].count
        }
        
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            return cellConfig(tableView, datas: datas, indexPath: indexPath)
        }
    }
    

    좋은 웹페이지 즐겨찾기