Search code examples
iosswiftuitableviewcustom-cell

UITableView does not show data correctly in my custom cell UILabel and reuse problem


I create my custom cell class and design my user interface with the code and constraints (I have 2 UILabels that hold my data in each row). I register my customcell class in the main viewController and load data in the tableview.

The problem is one of my UILabels fills with data but the second one not show its data until I scroll the table view or click right on that row. See images.

Before Scroll

enter image description here

After scroll

enter image description here

Here is my code:

class ProjectDetailsCustomCell: UITableViewCell {
    var key   : String?
    var value : String?

    var keyContainerView : UIView = {
        var containerView = UIView()
        containerView.translatesAutoresizingMaskIntoConstraints = false
        containerView.backgroundColor = UIColor(red: 0.867, green: 0.867, blue: 0.867, alpha: CGFloat(1))
        return containerView
    }()

    var keyView : UILabel = {
        var keyTextView = UILabel()
        keyTextView.translatesAutoresizingMaskIntoConstraints = false
        keyTextView.font = UIFont(name: "IRANSansWeb", size: 13)
        keyTextView.textAlignment = .center
        return keyTextView
    }()

    var valueView : UILabel = {
        var valueTextView = UILabel()
        valueTextView.translatesAutoresizingMaskIntoConstraints = false
        valueTextView.textAlignment = .center
        valueTextView.font = UIFont(name: "IRANSansWeb", size: 12)
        //valueTextView.textColor = UIColor(red: 0.2, green: 0.2, blue: 0.2, alpha: CGFloat(1))
        return valueTextView
    }()

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        self.addSubview(valueView)
        self.addSubview(keyContainerView)
        keyContainerView.addSubview(keyView)
        self.backgroundColor = UIColor.clear
        self.heightAnchor.constraint(equalToConstant: 42).isActive = true
        keyContainerView.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true
        keyContainerView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
        keyContainerView.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: 0.4).isActive = true
        keyContainerView.heightAnchor.constraint(equalToConstant: 40).isActive = true
        keyView.rightAnchor.constraint(equalTo: self.keyContainerView.rightAnchor).isActive = true
        keyView.topAnchor.constraint(equalTo: self.keyContainerView.topAnchor).isActive = true
        keyView.bottomAnchor.constraint(equalTo: self.keyContainerView.bottomAnchor).isActive = true
        keyView.widthAnchor.constraint(equalTo: self.keyContainerView.widthAnchor).isActive = true
        valueView.rightAnchor.constraint(equalTo: self.keyContainerView.leftAnchor).isActive = true
        valueView.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
        valueView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
        valueView.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: 0.6).isActive = true
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        if let key = key {
            keyView.text = key + value!
        }

        if let value = value {
            valueView.text = value
        }
    }

    override func awakeFromNib() {
        super.awakeFromNib()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

here is my data source code that populate the data array :

for i in 0..<self.detailsArray.count {
            // Populate our array list with the real data and restart the tableview
            self.dict = self.detailsArray[i]
            self.dataList.append(DetailsCellData.init(key: "شماره سفارش", value: String(self.dict["Id"] as! Int)))
            self.dataList.append(DetailsCellData.init(key: "قیمت", value: self.dict["Price"] as? String))
            self.dataList.append(DetailsCellData.init(key: "زمان و تاریخ سفارش", value: self.dict["DateTime"] as? String))
            self.dataList.append(DetailsCellData.init(key: "نام و نام خانوادگی کارفرما", value: self.dict["UserInformation"] as? String))
            self.dataList.append(DetailsCellData.init(key: "شماره تماس کارفرما", value: self.dict["UserPhone"] as? String))
            self.dataList.append(DetailsCellData.init(key: "نام خدمات دهنده", value: self.dict["ContractorInformation"] as? String))
            self.dataList.append(DetailsCellData.init(key: "شماره خدمات دهنده", value: self.dict["ContractorPhone"] as? String))
            self.dataList.append(DetailsCellData.init(key: "تاریخ درخواست خدمات", value: self.dict["ServiceDate"] as? String))
            self.dataList.append(DetailsCellData.init(key: "ساعت درخواست خدمات", value: self.dict["ServiceTime"] as? String))
            self.dataList.append(DetailsCellData.init(key: "مقدار کار", value: (self.dict["WorkAmmount"] as? String)! + " " + (self.dict["WorkUnit"] as? String)!))
            self.dataList.append(DetailsCellData.init(key: "هزینه تخمینی (ریال)", value: self.dict["EstimatedPrice"] as? String))
            self.tableview.reloadData()

here is my table view delegates code

func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if (dataList.count < 11){
        return 0
    } else {
        return dataList.count
    }
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableview.dequeueReusableCell(withIdentifier: "detailCustomCell", for: indexPath) as! ProjectDetailsCustomCell
    cell.key = self.dataList[indexPath.row].key
    cell.value = self.dataList[indexPath.row].value
    return cell
}

Solution

  • override func layoutSubviews() {
        super.layoutSubviews()
    
        updateLayout()
    }
    
    func updateLayout() {
        if let key = key {
            keyView.text = key + value!
        }
    
        if let value = value {
            valueView.text = value
        }
    }
    

    try this way, also add a line here

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableview.dequeueReusableCell(withIdentifier: "detailCustomCell", for: indexPath) as! ProjectDetailsCustomCell
        cell.key = self.dataList[indexPath.row].key
        cell.value = self.dataList[indexPath.row].value
        cell.updateLayout()
        return cell
    }