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.
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
}
}
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
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.