简体   繁体   English

标签文本更改时,重新计算UITableViewCell的高度

[英]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. 因此,当其标签的文本更改时,我在更新UITableViewCell的高度时遇到问题。

I'm not good at explaining thing, therefore I've created a repo on Github so that you can just grab and run. 我不擅长解释事物,因此我在Github上创建了一个存储库,以便您可以抓住并运行。 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. 每个单元中都有一个UILabel
  • I have a view model that will decide what's in the UILabel. 我有一个视图模型,它将决定UILabel中的内容。
  • I use RxSwift to register the changes in the view model and update the text of the UITable accordingly. 我使用RxSwift在视图模型中注册更改,并相应地更新UITable的文本。
  • At the same time, the cell will ask its delegate (in this case, the UITableViewController ) to recalculate its height. 同时,单元格将要求其委托(在这种情况下为UITableViewController )重新计算其高度。
  • The delegate will then call tableView.beginUpdates and tableView.endUpdates to update the height of the cell. 然后,委托将调用tableView.beginUpdatestableView.endUpdates来更新单元格的高度。

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() . 我试图调用tableView.reloadData() -> Infinite Loop ->无限循环
  • I tried to call tableView.reloadRows() -> This works but I don't know why. 我试图调用tableView.reloadRows() ->可以,但是我不知道为什么。

What I want to achieve: 我要实现的目标:

  • I want to keep Rx and MVVM together since I like the way Rx works. 我想将Rx和MVVM保持在一起,因为我喜欢Rx的工作方式。
  • 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 委托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. 这是我第一次在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. 当您仅给出top,lead,bottom和Trailing约束时。 Xcode will calculate height of label and increase cell size According to label height. Xcode将计算标签的高度,并根据标签的高度增加单元格的大小。 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. 在数组中添加了1个更大的文本来测试自我调整大小。

Self Sizing Tableview 自调整表格视图

Here is Screenshot of Out:- 这是Out的屏幕截图:-

I hope this answer is helpful for you. 我希望这个答案对您有帮助。

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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