简体   繁体   中英

Recalculate the height of the UITableViewCell when the text of the label changes

So I'm having a problem with updating the height of a UITableViewCell when the text of its label gets changed.

I'm not good at explaining thing, therefore I've created a repo on Github so that you can just grab and run. The problem should show up when you scroll up and down the table view (to make the cell reused).


What I did was :

  • I created a table view with self-size cells.
  • Each of the cells has a UILabel in it.
  • I have a view model that will decide what's in the UILabel.
  • I use RxSwift to register the changes in the view model and update the text of the UITable accordingly.
  • At the same time, the cell will ask its delegate (in this case, the UITableViewController ) to recalculate its height.
  • The delegate will then call tableView.beginUpdates and tableView.endUpdates to update the height of the cell.

Results :

  • When I scroll up the table view so that the first cell gets reused and then scroll down. The content of the first cell is duplicated across the table view (the second cell becomes a duplicate of the first one.)

What I tried :

  • I tried to call tableView.reloadData() . -> Infinite Loop
  • I tried to call tableView.reloadRows() -> This works but I don't know why.

What I want to achieve:

  • I want to keep Rx and MVVM together since I like the way Rx works.
  • I want to be able to change the label text of the cell and the height of the cell can be updated to fit the text.

Some code snippets: (Although it'd better to go check the repo out.):

Cell register view model

override func awakeFromNib() {
    super.awakeFromNib()

    viewModel.title
        .observeOn(MainScheduler.instance)
        .subscribe(onNext: { [weak self] title in
            guard let cell = self else { return }

            cell.label.text = title
            cell.delegate?.requestSizeRecalculate(cell: cell)
        })
        .disposed(by: disposeBag)
}

Delegate methods in UITableViewController

func requestSizeRecalculate(cell: SimpleCell) {
    print("Size recalculating....")

    method1(cell: cell)
    //method2(cell: cell)
    //method3(cell: cell)
}

private func method1(cell: SimpleCell) {
    // Will not cause infinite loop but will have duplicates.
    cell.setNeedsUpdateConstraints()
    tableView.beginUpdates()
    tableView.endUpdates()
}

private func method2(cell: SimpleCell) {
    // Will cause infinite loop
    tableView.reloadData()
}

private func method3(cell: SimpleCell) {
    // This method works pretty well.
    if let indexPath = tableView.indexPath(for: cell) {
        tableView.reloadRows(at: [indexPath], with: .none)
    }
}

It's my first time asking questions on Stackoverflow. I know I might have made things more complicated than it should be. But if anyone can offer any suggestions based on your experience, I would appreciate very much!

You can do:

tableView.beginUpdates()
tableView.reloadRows(at: [indexPathOfCell], with: .none)
tableView.endUpdates()

I have seen your code. Now you don't need to Calculate Height of row. when you give just top , leading , bottom and Trailing constrain. Xcode will calculate height of label and increase cell size According to label height. you need to pass just 1 method.

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{

   return UITableViewAutomaticDimension
}

you have done all the things correctly. you need to just write above method. Don't required this method now.

extension ViewController: SimpleCellDelegate {
    func requestSizeRecalculate(cell: SimpleCell) {
        print("Size recalculating....")

I have uploaded your project on this link with changes. Added 1 more large text in array to test self sizing.

Self Sizing Tableview

Here is Screenshot of Out:-

I hope this answer is helpful for you.

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM