UITableViewCell 约束直到我滚动 tableview 才更新

问题描述

以下是我更新tableview单元格内视图高度的代码

 override func layoutSubviews() {
    super.layoutSubviews()
    layout()
}

fileprivate func layout() {
    rootFlexContainer.frame.size.width = frame.width - 20
    rootFlexContainer.flex.layout(mode: .adjustHeight)
    if(rootFlexContainer.frame.height != 0) {
        tagsHeight.constant = rootFlexContainer.frame.height
      
    }
    
    
}

虽然这在我滚动之前不会反映出来,即重新创建单元格。如何更新视图的 TableViewCell 内的约束?

这是整个tableviewcell代码

import UIKit
import FlexLayout
import SDWebImage



class StoreListTableViewCell: UITableViewCell {


@IBOutlet weak var menuLbl: UILabel!


@IBOutlet weak var menuView: UIView!

@IBOutlet weak var cellBgview: UIView!
@IBOutlet weak var storeImg: UIImageView!
@IBOutlet weak var storeLocation: UILabel!
@IBOutlet weak var storeTitle: UILabel!

@IBOutlet weak var cellContainer: UIView!


@IBOutlet weak var stackView: UIStackView!


@IBOutlet weak var tagsHeight: NSLayoutConstraint!
var storeImgStr = ""
var storeTitleStr = ""
var storeLocationStr = ""
var score : Double = 0.0
var tagsstr = ""
var isMenuAvailble = 0
var retailerTags: [String]?
var cashbackString = ""
fileprivate let rootFlexContainer = UIView()



@IBOutlet weak var tagsView: UIView!


@IBOutlet weak var ratingBtn: UIButton!
override func awakeFromNib() {
    super.awakeFromNib()
    self.layoutIfNeeded()
    cellBgview.clipsToBounds = true
    cellBgview.layer.cornerRadius = 5
    cellContainer.layer.shadowColor = UIColor.lightGray.cgColor
    cellContainer.layer.shadowOpacity = 0.5
    cellContainer.layer.shadowRadius = 5.0
    cellContainer.layer.shadowOffset = CGSize(width: 0,height: 2)
    cellContainer.backgroundColor = UIColor.clear
    cellContainer.layer.cornerRadius = 5.0
    cellContainer.layer.borderColor = UIColor.white.cgColor
    cellContainer.layer.borderWidth = 0.5
    ratingBtn.layer.borderWidth = 1
    ratingBtn.layer.cornerRadius = 5
    tagsView.addSubview(rootFlexContainer)
          
    //cellContainer.layer.shadowPath = UIBezierPath(rect: cellBgview.bounds).cgPath
 }

func setSetupStoreUI()  {
    
    if isMenuAvailble == 1 {
        menuView.isHidden = false
        menuView.layer.cornerRadius = 10
    } else {
        menuView.isHidden = true
    }
    
    storeTitle.text = storeTitleStr
   // storeTitle.sizetoFit()
    storeLocation.text = storeLocationStr
    //storeLocation.sizetoFit()
    

    //.filter{ $0.name != " " }
    //storeImg.sd_imageIndicator = SDWebImageActivityIndicator.gray
    storeImg.backgroundColor = UIColor.hexStringToUIColor(hex: AppStrings.placeHolderColor)
    if let url = URL(string: storeImgStr.encoded),!(storeImgStr.isEmpty) {
        self.storeImg.sd_setimage(with: url)
        
    }
   
    
    menuLbl.text = AppLocalString.PREORDER_TEXT.localized()
    menuLbl.font = FontStyle.ProximaNovaBold(size: 12)

    storeTitle.font = FontStyle.ProximaNovaSemibold(size: 14)
    storeLocation.font = FontStyle.ProximaNovaRegular(size: 12)
    storeLocation.textColor = .gray
  //        ratingBtn.isHidden = (score == 0)
    ratingBtn.setTitle(score == 0 ? "-" : String(format: "%.1f",score),for: .normal)
    ratingBtn.backgroundColor = UIColor.hexStringToUIColor(hex: Utility.getratingColor(rating: score))
    ratingBtn.layer.borderColor = UIColor.hexStringToUIColor(hex: Utility.getratingColor(rating: score)).cgColor
   
    rootFlexContainer.subviews.forEach({ $0.removeFromSuperview() })
    //tagsView.willRemoveSubview(rootFlexContainer)
    //rootFlexContainer.frame = tagsView.frame
     //tagsView.addSubview(rootFlexContainer)
    rootFlexContainer.flex.direction(.row).wrap(.wrap).alignSelf(.auto).justifyContent(.start).paddingRight(2).define { (flex) in
        for i in 0..<((retailerTags?.count ?? 0) > 3 ? 3 : (retailerTags?.count ?? 0)) {
            let nameLabel = UIButton()
            nameLabel.isUserInteractionEnabled = false
            nameLabel.setTitle((retailerTags?[i] ?? "").trim(),for: .normal)
            nameLabel.setTitleColor(.black,for: .normal)
            nameLabel.titleLabel?.font = FontStyle.ProximaNovaRegular(size: 11)
            nameLabel.contentEdgeInsets = UIEdgeInsets(top: 1.5,left: 4,bottom: 1.5,right:4)
            nameLabel.layer.borderColor = UIColor.hexStringToUIColor(hex: AppStrings.grayBorderColor).cgColor
            nameLabel.layer.cornerRadius = 8
            nameLabel.layer.borderWidth = 1.0
            nameLabel.sizetoFit()
            flex.addItem(nameLabel).margin(2)
            
        }
        if cashbackString != "" {
        let cashbackLabel = UIButton()
            
            cashbackLabel.backgroundColor = UIColor.hexStringToUIColor(hex: AppStrings.orangeCashbackColor)
            cashbackLabel.isUserInteractionEnabled = false
            cashbackLabel.setTitle(cashbackString,for: .normal)
            cashbackLabel.setTitleColor(.black,for: .normal)
            cashbackLabel.titleLabel?.font = FontStyle.ProximaNovaRegular(size: 10)
            cashbackLabel.contentEdgeInsets = UIEdgeInsets(top: 1.5,left: 5,right: 5)
            cashbackLabel.layer.cornerRadius = 5
            cashbackLabel.layer.borderWidth = 0
            cashbackLabel.sizetoFit()
            flex.addItem(cashbackLabel).margin(2)
        }
          
    }
    rootFlexContainer.flex.layout()
    if retailerTags?.count ?? 0 == 0 {
        tagsView.isHidden = true
    } else {
        tagsView.isHidden = false
    }
    
   
    
}


override func layoutSubviews() {
    super.layoutSubviews()
    layout()
}

fileprivate func layout() {
    rootFlexContainer.frame.size.width = frame.width - 20
    rootFlexContainer.flex.layout(mode: .adjustHeight)
    if(rootFlexContainer.frame.height != 0) {
        tagsHeight.constant = rootFlexContainer.frame.height
      
    }
    
    
}



override func setSelected(_ selected: Bool,animated: Bool) {
    super.setSelected(selected,animated: animated)
    
    // Configure the view for the selected state
}

}

以下是故事板的视图层次结构

enter image description here

解决方法

一些观察 -

1. layoutIfNeeded()

内不必要的 awakeFromNib() 调用
override func awakeFromNib() {
    super.awakeFromNib()

    /*
    self.layoutIfNeeded() // Not Necessary,Remove it.
    */
    

    // No other changes to current implementation
}

2.不需要以下内容,请将其删除。

/* Not necessary,Remove it.
override func layoutSubviews() {
    super.layoutSubviews()
    layout()
}

fileprivate func layout() {
    rootFlexContainer.frame.size.width = frame.width - 20
    rootFlexContainer.flex.layout(mode: .adjustHeight)
    if(rootFlexContainer.frame.height != 0) {
        tagsHeight.constant = rootFlexContainer.frame.height
    }
}
*/

3.在填充所有详细信息的方法中,进行以下更改

func setSetupStoreUI()  {
    // No changes to current implementation

    /* Remove this,we will update later
    rootFlexContainer.flex.layout()
    */

    if retailerTags?.count ?? 0 == 0 {
        tagsView.isHidden = true
    } else {
        tagsView.isHidden = false
    }
    
    // Copied as is from `layout()` 
    rootFlexContainer.frame.size.width = frame.width - 20
    rootFlexContainer.flex.layout(mode: .adjustHeight)
    if (rootFlexContainer.frame.height != 0) {
        tagsHeight.constant = rootFlexContainer.frame.height
    }

    // do a manual layout (on contentView,NOT self)
    self.contentView.layoutIfNeeded()
}
,

你必须告诉表格视图控制器你的单元格高度已经改变了。

最常见的方法是协议/委托模式或(swift 首选)闭包。

例如...

在您的单元格类中:

class MyTableViewCell: UITableViewCell {
    
    // "callback" closure
    var cellHeightChanged: (()->())?
    
    // whatever happens that you need to change the cell height
    func heightChanged() -> Void {
        tagsHeight.constant = rootFlexContainer.frame.height
        cellHeightChanged?()
    }

}

然后,在您的控制器中,在 cellForRowAt 中:

cell.cellHeightChanged = {
    tableView.performBatchUpdates(nil,completion: nil)
}