简体   繁体   中英

How can I reinitialize a UITableViewCell in Swift?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM