Separating Data Source to another class in Swift

前端 未结 3 689
时光取名叫无心
时光取名叫无心 2020-12-13 20:21

I\'m trying to keep my view controllers clean as described in this article objc.io Issue #1 Lighter View Controllers. I tested this method in Objective-C and it works fine.

相关标签:
3条回答
  • 2020-12-13 20:39

    Create a property for data source and use it with your tableview.

    class ViewController: UIViewController {
    
      @IBOutlet weak var tableView: UITableView!
      var dataSource:TableDataSource!
    
      override func viewDidLoad() {
        super.viewDidLoad()
    
        dataSource = TableDataSource(items: ["One", "Two", "Three"], cellIdentifier: "Cell")
    
       tableView.dataSource = dataSource
    
      }
    }
    
    0 讨论(0)
  • 2020-12-13 20:42

    I used the below code, for more generic approach, as a try..

    import UIKit
    
    class CustomDataSource<ItemsType, CellType:UITableViewCell>: NSObject, UITableViewDataSource {
    
        typealias ConfigureCellClosure = (_ item: ItemsType, _ cell: CellType) -> Void
        private var items: [ItemsType]
        private let identifier: String
        private var configureCellClosure: ConfigureCellClosure
    
    
        init(withData items: [ItemsType], andId identifier: String, withConfigBlock config:@escaping ConfigureCellClosure) {
    
            self.identifier = identifier
            self.items      = items
            self.configureCellClosure = config
        }
    
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return items.count
        }
    
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: self.identifier, for: indexPath) as! CellType
            configureCellClosure(items[indexPath.row], cell)
            return cell
        }
    
        func item(at indexpath: IndexPath) -> ItemsType {
    
            return items[indexpath.row]
        }
    
    }
    

    In view controller

       var dataSource: CustomDataSource<CellObject, CustomTableViewCell>?
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
             dataSource = CustomDataSource<CellObject, CustomTableViewCell>(withData: customDataStore.customData(), andId: CustomTableViewCell.defaultReuseIdentifier) { (cellObject, cell) in
                cell.configureCell(with: cellObject)
            }
            customTableView.dataSource = dataSource
    
            // Do any additional setup after loading the view.
    }
    

    Used this approach in my small project WorldCountriesSwift

    0 讨论(0)
  • 2020-12-13 20:54

    Extending the accepted answer by "ayalcinkaya", which explains the how but not the why:

    Most probably what is happening is that your TableDataSource is being deallocated as tableview.dataSource is a weak reference, that is why creating a property solves the problem, as it creates a strong reference and avoids the dataSource delegate being deallocated.

    0 讨论(0)
提交回复
热议问题