I'm trying to add some data to a UITableView object.
My problem is that none of the methods in my data source object is called during runtime.
I already checked that the UITableView itself is displayed.
When I call providerTable.reloadData() just the numberOfSections(in tableView: UITableView) -> Int and tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int method is called, but never tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
import UIKit
class ProviderViewController: UIViewController {
let navigationBar = { () -> UINavigationBar in
let bar = UINavigationBar()
bar.setItems([
{ () -> UINavigationItem in
let item = UINavigationItem()
item.title = "a title"
return item
}()
], animated: false)
bar.translatesAutoresizingMaskIntoConstraints = false
return bar
}()
let providerTable = { () -> UITableView in
let providerDataSource = ProviderTableDataSource()
let table = UITableView()
table.dataSource = providerDataSource
table.translatesAutoresizingMaskIntoConstraints = false
table.register(ProviderTableViewCell.self, forCellReuseIdentifier: "providerCell")
return table
}()
override func viewDidLoad() {
super.viewDidLoad()
self.setupWindow()
}
func setupWindow() -> Void {
view.backgroundColor = .white
view.addSubview(navigationBar)
view.addSubview(providerTable)
// Set constraints
var constraints = [NSLayoutConstraint]()
// navbar
constraints.append(NSLayoutConstraint(item: navigationBar,
attribute: .width,
relatedBy: .equal,
toItem: view,
attribute: .width,
multiplier: 1,
constant: 0))
constraints.append(NSLayoutConstraint(item: navigationBar,
attribute: .left,
relatedBy: .equal,
toItem: view,
attribute: .left,
multiplier: 1,
constant: 0))
constraints.append(NSLayoutConstraint(item: navigationBar,
attribute: .top,
relatedBy: .equal,
toItem: view.safeAreaLayoutGuide,
attribute: .top,
multiplier: 1,
constant: 0))
// provider table
constraints.append(NSLayoutConstraint(item: providerTable,
attribute: .width,
relatedBy: .equal,
toItem: view,
attribute: .width,
multiplier: 1,
constant: 0))
constraints.append(NSLayoutConstraint(item: providerTable,
attribute: .left,
relatedBy: .equal,
toItem: view,
attribute: .left,
multiplier: 1,
constant: 0))
constraints.append(NSLayoutConstraint(item: providerTable,
attribute: .top,
relatedBy: .equal,
toItem: navigationBar,
attribute: .bottom,
multiplier: 1,
constant: 0))
constraints.append(NSLayoutConstraint(item: providerTable,
attribute: .bottom,
relatedBy: .equal,
toItem: view,
attribute: .bottom,
multiplier: 1,
constant: 0))
// activate constraints
view.addConstraints(constraints)
}
}
The data source object: import UIKit
class ProviderTableDataSource: NSObject, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "providerCell", for: indexPath) as! ProviderTableViewCell
cell.charterProvider = CharterProviders.providers[indexPath.row]
return cell
}
}
You are not keeping a strong reference to the ProviderTableDataSource that you create when you create your table view:
let providerTable = { () -> UITableView in
let providerDataSource = ProviderTableDataSource()
let table = UITableView()
table.dataSource = providerDataSource
table.translatesAutoresizingMaskIntoConstraints = false
table.register(ProviderTableViewCell.self, forCellReuseIdentifier: "providerCell")
return table
}()
UITableView's dataSource property is weak, so you can't rely on that to hold a strong reference to a ProviderTableDataSource. See the docs here:
https://developer.apple.com/documentation/uikit/uitableview/1614955-datasource?changes=_6
What you want to do is probably something like this:
class ProviderViewController: UIViewController {
private let providerDataSource = ProviderTableDataSource()
private(set) lazy var providerTable: UITableView = {
let table = UITableView()
table.dataSource = self.providerDataSource
table.translatesAutoresizingMaskIntoConstraints = false
table.register(ProviderTableViewCell.self, forCellReuseIdentifier: "providerCell")
return table
}()
// [...]
}
This way, the view controller is holding a strong reference to the ProviderTableDataSource so it will not be released after the creation of the table view.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With