循环中的 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

Swift 3 tableView 未在 reloadData() 上更新