如何在 Swift 中重新初始化 UITableViewCell?

问题描述

我使用 UITableViewCell 来显示数据。当视图加载时,数据为空,但是一旦 api 调用完成,我想重新初始化 UITableViewCell 以便数据可以出现。我正在使用以下代码,但 TableView.reloadData() 不会重新初始化 UITableViewCell,因此不会重新加载数据。

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,Chart.leftAnchor.constraint(equalTo: self.contentView.leftAnchor,])
        let data = ChartHelpers().makeLineChart(data: Info?.Values ?? [Double]())
        Chart.data = data
        self.contentView.layoutIfNeeded()
     }

     required init?(coder aDecoder: NSCoder) {
       super.init(coder: aDecoder)
    }
}

视图控制器


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
    }
}

解决方法

最好不要在init中进行配置,因为cell实例可能会被重用。应在单元出列时完成设置。这可以通过设置方法或通过设置属性来完成,就像您在此处使用 Info 所做的那样(顺便说一句,将其命名为 info 会更 Swifty)。

在此处获得所需内容的最简单方法是将 didSet 添加到您的 Info 属性并调用那里的设置方法:

var info: Information? {
    didSet {
        let data = ChartHelpers().makeLineChart(data: Info?.Values ?? [Double]())
        Chart.data = data
        self.contentView.layoutIfNeeded()
    }
}

尽管从长远来看,其他重构可能会更好。

,

didSet 添加到您的 Info 变量以触发构建图表。

var Info: Information? {
   didSet {
     let data = ChartHelpers().makeLineChart(data: Info?.Values ?? [Double]())
     Chart.data = data
     self.contentView.layoutIfNeeded()
   }
}

didSet 观察器不会在 init 期间触发,因此当您在 API 调用后拥有有效数据时,您需要在单元格重新加载时再次调用序列。