使用几种不同类型的单元格滚动 UITableView 不够平滑

Posted

技术标签:

【中文标题】使用几种不同类型的单元格滚动 UITableView 不够平滑【英文标题】:Scrolling UITableView with few different types of cells not smooth enough 【发布时间】:2015-03-11 18:53:34 【问题描述】:

我需要在一个非常复杂的表格视图中包含几种不同的单元格类型。我在那些具有不同重用标识符的不同单元类中注册了 10 个 xib。问题是,当我第一次(从上到下)滚动表格视图时,我可以看到它有点滞后。但是,在我滚动到底部之后,再滚动回顶部和底部再次运行顺利。问题似乎出在 dequeueReusableCellWithIdentifier: 如果目前没有所需类型的可重用单元格,则在滚动时似乎无法足够快地加载不同的 xib 文件。这就是为什么第一次滚动会滞后,但是当每种类型的可重用单元都加载了足够多时,它就会开始平滑滚动。

有没有办法为 UITableView 预加载可重用的单元格。因此,例如,我可以加载每种 xib 类型 3 次(因此当调用 dequeueReusableCellWithIdentifier 时,tableview 将在内存中加载 30 个可重复使用的单元格(10 种单元格类型中的每个单元格 3 个))?稍后我需要在应用商店上发布应用,因此不允许使用任何私有 api。或者,在这种情况下,您还有其他可能的解决方案来提高性能吗?

【问题讨论】:

您在模拟器上看到滞后还是仅在设备上看到滞后(什么类型的设备/ios 版本)?如果 dequeueReusableCellWithIdentifier 确实有问题,也可以通过 Xcode Instruments 进行检查。 在模拟器和设备(iphone 5 ios 8)上都滞后,但正如我所说的,仅在第一次从上到下滚动时。完全滚动后,它开始平滑滚动。是的,我检查了仪器,看起来 dequeueReusableCellWithIdentifier 是问题所在。 您应该在 UITableView 实例中通过 -[dequeueReusableCellWithIdentifier:(NSString *)identifier] 注册您的单元格 xib。您可能需要覆盖自定义单元类中的 -[prepareForReuse] 。所以单元格实例将被重用。减少单元实例数将提高您的速度。 【参考方案1】:

我记得,CoreGraphics 会在每个单元格首次出现时对其进行检查,并执行一些混合计算,以使标签和视图按照您设计的方式显示。

可以通过在 InterfaceBuilder 中将每个视图(标签、按钮、视图)设置为不透明来缓解这种减速。

减少 alpha != 1 的视图数量。

将背景设置为白色,或者您使用的任何颜色,而不是清晰的。

查看这个人的解释和示例代码,了解他如何让动态表格视图尽可能快地滚动。 https://github.com/kevinlawler/fastscrolling

*该链接是一个旧示例,但原则仍然适用于 afaik

【讨论】:

【参考方案2】:

如果您在应用程序中使用故事板,则在将 tableView 的父视图控制器声明为 UITableViewDelegate 后,您可以在表格定义中定义多种单元格类型。

您可能是对的,XIB 的初始负载正在杀死您。

【讨论】:

是的,我需要 10 个具有完全不同布局的不同 xib,所以说我不需要它们对我没有多大帮助:) 还有其他建议吗? 您可以有 10 种不同的布局。您只需将它们放在同一个 XIB 中。看看箭头在哪里。您在那里设置自定义单元格的数量。然后,当加载视图控制器并且您的问题应该消失时,XIB 会一次性加载。 你的意思是我应该把不同的布局放在一个UITableViewCell下面的内容视图下面吗?是的,这可能会解决滚动时单元格加载速度过慢的问题,但这不是一个非常优雅的解决方案,而且很难维护,所以我会寻找其他解决方案。 是的。您会在左侧看到表格视图单元的列表。每个都可以有自己的布局。每个都应该有自己的重用标识符,并且您绝对应该重命名资源管理器上的单元格以保持自己的理智。我同意 UI 可能有点难以使用,但它是针对您的问题而设计的。我支持具有 10 种不同结果类型的应用,因此我们有 10 个自定义单元原型。 好的,我明白你的意思了。感谢您的建议。我不确定这是否会有所帮助,但在我正在工作的项目中,无论如何我都不能使用故事板,不幸的是,xib 中的视图控制器不支持动态单元原型。【参考方案3】:

使用预加载单元创建二级缓存解决了滚动问题。在 viewDidLoad 上,我正在注册笔尖(使用 registerNib:forCellReuseIdentifier:),之后也在 viewDidLoad 中创建一个可变数组,我使用 dequeueReusableCellWithIdentifier: 为每个笔尖加载几个单元格,然后将这些单元格放入我的可变数组中。稍后在 cellForRowAtIndexPath 中,我首先检查是否在可变数组中预加载了所需类型的单元格。如果我有它,那么我返回这个单元格并将其从数组中删除(在这种情况下,我不调用 dequeueReusableCellWithIdentifier:)。如果我的缓存中没有它,那么我调用 dequeueReusableCellWithIdentifier: 来获取单元格。

编辑: 事实证明,延迟的主要原因是我在 awakeFromNib 中使用的一些简单的反应性可可绑定。移除这些反应性可可绑定后,即使没有任何额外的单元格预加载,一切都开始顺利滚动。

【讨论】:

【参考方案4】:

我用的是诡计。

1) 在实际的前面添加几个零高度单元格。

2) 根据需要将其出列。

3) 将 cell.clipToBounds 设置为 YES。

现在已经完成了。

【讨论】:

以上是关于使用几种不同类型的单元格滚动 UITableView 不够平滑的主要内容,如果未能解决你的问题,请参考以下文章

UITableViewCells 中的 UITextFields - 当单元格消失时,文本会消失

是否有某些静态单元填充了其余的视图?

UITableview 滚动时有两个不同的自定义单元格重叠

图像未立即在表格视图中加载

滚动时 UITableViewCell 自动布局抖动的动态单元格高度问题

滚动自定义表格视图单元格时,UITableViewCell 不稳定