【问题标题】:heightForRowAtIndexPath being called for all rows & how many rows in a UITableView before performance issues?在性能问题之前,所有行都调用了 heightForRowAtIndexPath 以及 UITableView 中有多少行?
【发布时间】:2011-03-16 10:50:17
【问题描述】:

我以为我已经阅读了 UITableView 的内容,heightForRowAtIndexPath 不会在所有行上都被调用,而只会在可见的行上被调用。然而,这不是我所看到的。例如,我看到数百个对heightForRowAtIndexPath 的呼叫,因为iPhone 的方向被改变的简单情况。

因此,我在这里假设,对于实现了heightForRowAtIndexPathUITableView,它确实(即heightForRowAtIndexPath)被所有行(不仅仅是可见行)调用...如果这让我知道不太正确。

问题:鉴于上述情况,在通常发生性能问题之前,UITableView(实现heightForRowAtIndexPath)中有多少行?

有没有办法解决性能问题?即为每行设置一个标称/标准高度,而不是实现heightForRowAtIndexPath,但只有在显示时正确设置每行高度并在此处正确设置...但是哪种方法可以做到这一点?

【问题讨论】:

    标签: iphone ios uitableview heightforrowatindexpath


    【解决方案1】:

    查看tableView:heightForRowAtIndexPath: documentation中的讨论部分

    该方法允许委托指定具有不同高度的行。如果实现了此方法,则它返回的值将覆盖为给定行的 UITableView 的 rowHeight 属性指定的值。

    使用 tableView:heightForRowAtIndexPath: 代替 rowHeight 属性会影响性能。每次显示表视图时,它都会在委托上为其每一行调用 tableView:heightForRowAtIndexPath:,这可能会导致具有大量行(大约 1000 或更多)的表视图出现严重的性能问题。

    所以你应该使用 UITableView 的rowHeight 属性。如果您需要不同的高度,那您就不走运了,因为您必须使用tableView:heightForRowAtIndexPath:

    AFAIK 无法更改显示时的行高。
    tableview 之前必须知道正确的大小,否则会一直出现难看的位置偏移。

    【讨论】:

    • 哦,但话又说回来,我这里有一个 tableview,里面有大约 500 个项目,性能似乎很差 - 所以这似乎意味着你真的不能有一个 tableView 里面有这么多行实际上没有?
    • 这意味着你不能有 500 行不同的高度。如果所有行都具有相同的高度(在 rowHeight 属性中设置),那么性能影响应该不会那么大。
    • 我真的希望苹果能解决这个不能拥有大量行的动态行高的缺陷。我很想知道是否有其他方法可以动态管理 UITableView 中的行数,以保持数字最小。
    • 实际上,我不完全确定他们是否可以修复它。出于完全不同的原因,我开始开发自己的自定义 tableView,目的是重新创建 Apple 的功能并添加我自己的功能。我很快意识到我必须知道所有单元格的高度才能使其工作。因为您无法预测表格的位置(它可以通过编程方式跳转),所以您必须准备好在任何位置布局视图,这意味着您必须知道所有高度。唯一的选择是计算每个布局的所有先前高度,这将非常昂贵。
    • 这要了我的命,但至少我有一个答案。你认为他们至少可以做到,所以他们可以计算出前 50 行,然后在用户滚动时分批计算其余的行,就像他们在 CoreData 中使用 fethBatchSize 一样。我的应用有时会有 1000 多行,有些可能有不同的行大小 - 加载速度非常慢
    【解决方案2】:

    我想我找到了解决办法。

    在 iOS 7 苹果引入了一些新的 tableview 属性。其中之一是:

    tableView:estimatedHeightForRowAtIndexPath:
    

    所以如果你提供一个估计的行高,例如,当 tableView:heightForRowAtIndexPath: 在表格显示之前被重复调用时,它只会为表格的可见单元格调用;对于剩余的单元格,使用估计的高度。

    以下是该信息的来源:https://books.google.gr/books?id=wLaVBQAAQBAJ&pg=PT521&lpg=PT521&dq=heightforrowatindexpath+only+for+the+visible+cells&source=bl&ots=7tuwaMT5zV&sig=h3q8AaFvoCgcrPu2fQchVkIEjwg&hl=en&sa=X&ved=0CEMQ6AEwBWoVChMInLK0xbPuxwIVCbUaCh3_nQWG#v=onepage&q=heightforrowatindexpath%20only%20for%20the%20visible%20cells&f=false

    【讨论】:

      【解决方案3】:

      我的天哪,我花了一个多小时试图找到我的性能问题的根源!

      最后我还发现了数百个对 heightForRowAtIndexPath 的调用和一个搜索 给我这个线程。这真的很烦人。 仅显示 250 个项目时,性能已经下降。谢天谢地,我现在要显示的单元格都具有相同的大小。但我可以想象有人想为包含超过 200 个项目的 tableView 显示一些不同的单元格!

      修复这个苹果!

      干杯

      【讨论】:

        【解决方案4】:

        在具有大量行数和动态单元格高度的 tableViews 中提高性能的一种方法是在首次计算单元格高度时对其进行缓存。

        实现此目的的一种简单方法是保留 NSMutableDictionary,其中键是单元格中记录的 id(或您可能拥有的任何其他标识符),值是带有高度的 NSNumber行的。首次计算高度后,通过记录 ID 将其存储为 NSMutableDictionary。在tableView:heightForRowAtIndexPathtableView:estimatedHeightForRowAtIndexPath: 中检查字典中缓存的高度,如果找到则返回。如果没有找到,计算高度,并在返回高度之前存储在缓存中。

        您可能必须小心使更改高度的行的缓存无效。例如,如果您的某个单元格中有一个展开按钮,则需要在点击展开按钮后从缓存中删除该单元格的高度委托方法调用高度。

        如果您尝试在表格显示时一次显示 1000 个单元格,您可能仍然会遇到性能问题,因为它可能会为每一行调用 height 方法。解决此问题的方法是,如果可能的话,在后台任务中首先预热缓存,然后再显示单元格。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-09-06
          • 2011-06-28
          相关资源
          最近更新 更多