ios – How to properly update UITableView Cell size and layout after configure it with data?


So, I am facing a problem where I need to hide or show button after configuring the cell and the cell just does not display it properly at initial load. It is not appearing in any cell.

I tried a lot of different ways of applying layoutIfNeeded and etc everywhere in the code.

Details:
I have a UILabel with some text filled in method “configure” and method “updateExpandButtonTitle” which I call in the same “configure”. This method decides by the number of lines in my text should it be hidden or not. But the first time it will be hidden before I reload my table. I need to fix this.
Also, I have to mention that on that button tap I set my UILabel number of lines to Zero and do the tableView.beginUpdate and tableView.endUpdate.

Here is some code:

CELL:

    // MARK: - Properties -
    
    private var updateCell: ((_: NIPostFeedTableViewCell) -> Void)?
    
    // MARK: - Life Cycle -
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        
        setupView()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        
        setupView()
    }
    
    // MARK: - Internal -
    
    func configure(with post: NIPost, update: @escaping (_: NIPostFeedTableViewCell) -> Void) {
        postTitleLabel.text = post.title
        postDescriptionLabel.text = post.previewText
        postLikesLabel.text = (post.likesCount ?? .zero).stringValue
        postDateLabel.text = post.timeshamp?.convertToDate()
        updateCell = update
        
        updateExpandButtonVisibility()
    }
}

private extension NIPostFeedTableViewCell {
    func setupView() {
        contentView.backgroundColor = .white
        
        contentView.addSubview(mainStackView)
        
        mainStackView.addArrangedSubview(postTitleLabel)
        mainStackView.addArrangedSubview(postDescriptionLabel)
        mainStackView.addArrangedSubview(horizontalStackView)
        mainStackView.addArrangedSubview(postExpandButton)
        
        horizontalStackView.addArrangedSubview(likesStackView)
        horizontalStackView.addArrangedSubview(postDateLabel)
        
        likesStackView.addArrangedSubview(postLikesImageView)
        likesStackView.addArrangedSubview(postLikesLabel)
        
        NSLayoutConstraint.activate([
            mainStackView.topAnchor.constraint(
                equalTo: contentView.topAnchor,
                constant: Constant.defaultVerticalInset
            ),
            mainStackView.bottomAnchor.constraint(
                equalTo: contentView.bottomAnchor,
                constant: -Constant.defaultVerticalInset
            ),
            mainStackView.leadingAnchor.constraint(
                equalTo: contentView.leadingAnchor,
                constant: Constant.defaultHorizontalInset
            ),
            mainStackView.trailingAnchor.constraint(
                equalTo: contentView.trailingAnchor,
                constant: -Constant.defaultHorizontalInset
            ),
            postExpandButton.heightAnchor.constraint(equalToConstant: 35)
        ])
    }
     
    @objc func tappedExpandButton() {
        postDescriptionLabel.numberOfLines = postDescriptionLabel.numberOfLines == .zero ? Constant.defaultDescriptionNumberOfLines : .zero
        
        updateExpandButtonTitle()
        updateCell?(self)
    }
    
    func updateExpandButtonTitle() {
        let isTitleNeededToBeChanged = postExpandButton.titleLabel?.text == Constant.expandTitle
        let newTitle = isTitleNeededToBeChanged ? Constant.collapseTitle : Constant.expandTitle
        
        postExpandButton.setTitle(newTitle, for: .normal)
    }
    
    func updateExpandButtonVisibility() {
        let isButtonNeeded = postDescriptionLabel.doesTextFitInLines()
        postExpandButton.isHidden = isButtonNeeded
    }
}

CONTROLLER:

'cellForRowAt' - cell.configure(with: post, update: updateCell)

func updateCell(_ cell: NIPostFeedTableViewCell) {
        UIView.animate(withDuration: 0.2) {
            cell.layoutIfNeeded()
            self.tableView.beginUpdates()
            self.tableView.endUpdates()
        }
    }


and the code for UILabelExtension:

extension UILabel {
    func doesTextFitInLines() -> Bool {
        guard let text = self.text else {
            return false
        }

        let fontAttributes = [NSAttributedString.Key.font: self.font as Any]
        let boundingRect = text.boundingRect(
            with: CGSize(width: self.bounds.width, height: CGFloat.greatestFiniteMagnitude),
            options: .usesLineFragmentOrigin,
            attributes: fontAttributes,
            context: nil
        )

        let calculatedLines = Int(boundingRect.height / self.font.lineHeight)

        return calculatedLines <= self.numberOfLines
    }
}

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img