在我滚动 tableview 之前,UITableViewCell 约束不会更新

UITableViewCell constraints not updated till I scroll 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{ [=11=].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({ [=11=].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, bottom: 1.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
}

}

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

您必须告诉 table 视图控制器您的单元格高度已更改。

最常见的方法是 protocol/delegate 模式或(swift 首选)闭包。

例如...

在你的手机里 class:

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

几点观察 -

1.在 awakeFromNib()

中不必要的 layoutIfNeeded() 调用
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()
}