循环中的 tableView reloadData 不会在每次通过时绘制单元格
Posted
技术标签:
【中文标题】循环中的 tableView reloadData 不会在每次通过时绘制单元格【英文标题】:tableView reloadData in loop not drawing cells on each pass 【发布时间】:2017-11-29 01:16:07 【问题描述】:我在应用程序的多个位置循环调用了 tableView.reloadData()。基本思路是这样的:
let dataSourceArray = []
for arrayItem in anotherArray
dataSourceArray.append(arrayItem)
self.tableView.reloadData()
我想要实现的是让 tableView 在加载到模型数组时绘制每个单元格。
当前发生的情况是,一旦循环完成,所有单元格都会出现。
这一切都是在主线程中完成的,但是我无论如何都尝试分派到主线程以进行 reloadData 调用。那没什么区别。我在 reloadData 之后尝试了 tableView.layoutIfNeeded() 也没有任何区别。
在 cellForRowAtIndexPath 和 heightForRow... 方法中放置断点表示在循环中的每次传递时正常的 tableView 调用。但是由于某种原因,单元格在循环完成之前不会在屏幕上绘制。
除了我上面尝试的方法之外,是否有强制 tableView 在每次通过时绘制单元格?
【问题讨论】:
你为什么打电话给reloadData
?使用insertRows(at
并插入每一行而不为单行重新加载整个表视图。
【参考方案1】:
我相信原因是因为你的元素的循环将很快完成(毫秒),因此你不会注意到增量变化。
【讨论】:
不,原因是 UI 在当前的 runloop 有机会完成之前不会更新,并且在此循环完成之前不会发生。它与发生的速度无关。【参考方案2】:您需要像下面这样在全局队列中运行外循环并将 reloadData 调度到主队列。
var dataSourceArray = [ String ]()
@IBAction func
DoA( _: Any? )
let anotherArray = [ "A", "B", "C" ]
DispatchQueue.global().async
for arrayItem in anotherArray
self.dataSourceArray.append( arrayItem )
DispatchQueue.main.async
self.tableView.reloadData()
Thread.sleep( forTimeInterval: 1 )
【讨论】:
【参考方案3】:如果您想要一个清晰可见的动画,那么您可以在每次追加之间强制设置一个计时器;使用 UIView.animate 或 UIView.transition...我更喜欢过渡方法,它为您提供了一些选项,使您的更改更加整洁。
这是你可以做的一个示例(不要直接复制粘贴,调整到你自己的,我在操场上写的没有测试它)
var i = 0
func addItem()
if i == anotherArray.count
return
UIView.transition(with: tableView, duration: 0.3, options: [.allowAnimatedContent, .transitionCrossDissolve], animations: // content that is going to animate
dataSourceArray.append(anotherArray[i])
tableView.reloadData()
) // completion block
i += 1
addItem()
除此之外,您可以将 tableView 的内容模式(很可能来自情节提要)更改为 .top
,这样每次更改您的 tableView 都会保持在顶部而不是四处跳动(https://developer.apple.com/documentation/uikit/uiview/1622619-contentmode )。如果您使用自动布局,这将特别有帮助
【讨论】:
以上是关于循环中的 tableView reloadData 不会在每次通过时绘制单元格的主要内容,如果未能解决你的问题,请参考以下文章
如何让 tableView.reloadData() 与核心数据正常工作?
Swift:tableView.reloadData() 表中没有数据
未调用 tableView reloadData cellForRowAtIndexPath
tableView reloadData 和 deselectRowAtIndexPath
tableView.reloadData() 和 DispatchQueue 无法在不同的视图控制器中重新加载 tableview