I am using a UITableViewCell
to show data. When the view loads, the data is empty, however once the API call is complete I want to reinitialize the UITableViewCell
so that the data can appear. I am using the following code, but TableView.reloadData()
does not reinitialize the UITableViewCell
so the data does not reload.
TableViewCell
class TableViewCell: UITableViewCell {
var Info: Information?
let Chart = LineChartView(frame: .zero)
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
print("initialized")
self.contentView.addSubview(Chart)
Chart.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
Chart.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 10),
Chart.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -10),
Chart.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -10),
Chart.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 10),
])
let data = ChartHelpers().makeLineChart(data: Info?.Values ?? [Double]())
Chart.data = data
self.contentView.layoutIfNeeded()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
`
ViewController
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var Info: Information?
let TableView = UITableView(frame: .zero)
override func viewDidLoad() {
super.viewDidLoad()
APICall()
setUpUI()
}
func setUpUI() {
view.addSubview(TableView)
TableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
TableView.topAnchor.constraint(equalTo: view.topAnchor),
TableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
TableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
TableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
])
self.TableView.register(TableViewCell.self, forCellReuseIdentifier: "Chart")
TableView.delegate = self
TableView.dataSource = self
TableView.reloadData()
view.layoutIfNeeded()
}
func APICall() {
API().fetchInformation(Name: "John Doe") { (Info) in
//success connecting to api
DispatchQueue.main.async {
self.Info = Info
self.TableView.reloadData()
}
} failure: { (error) in
//failure connecting to api
}
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = TableView.dequeueReusableCell(withIdentifier: "Chart", for: indexPath) as! TableViewCell
tableView.rowHeight = 300
cell.Info = self.Info
return cell
}
}
It's best not to do configuration in the init, as the cell instance may be reused. Setup should be done when dequeuing a cell. This can be done with a setup method, or by setting the properties, as you have done here with Info
(by the way, it would be Swifty-er to name that info
).
The easiest way to get what you want here would be to add a didSet
to your Info
property and call the setup methods there:
var info: Information? {
didSet {
let data = ChartHelpers().makeLineChart(data: Info?.Values ?? [Double]())
Chart.data = data
self.contentView.layoutIfNeeded()
}
}
Although other refactors may be better in the long run.