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.
Add a didSet
to your Info
var to trigger building the chart.
var Info: Information? {
didSet {
let data = ChartHelpers().makeLineChart(data: Info?.Values ?? [Double]())
Chart.data = data
self.contentView.layoutIfNeeded()
}
}
A didSet observer doesn't fire during init so you need to call the sequence again when the cell reloads when you have valid data after the API call.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.