Reputation: 55
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
}
}
Upvotes: 3
Views: 714
Reputation: 9829
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.
Upvotes: 6