简体   繁体   English

循环中的tableView reloadData不在每次通过时都绘制单元格

[英]tableView reloadData in loop not drawing cells on each pass

I have a tableView.reloadData() call in a loop in several places in my app. 我在我的应用程序中的多个位置循环调用了tableView.reloadData()。 the basic idea is like this: 基本思想是这样的:

let dataSourceArray = []
for arrayItem in anotherArray {
     dataSourceArray.append(arrayItem)
     self.tableView.reloadData()
}

What I'm trying to achieve is to have the tableView draw each cell as it is loaded into the model array. 我想要实现的是让tableView在加载到模型数组中时绘制每个单元格。

What is currently happening is that all the cells appear once the loop is complete. 当前正在发生的事情是,一旦循环完成,所有单元格就会出现。

This is all being done in the main thread, however I tried anyway to dispatch to main thread for the reloadData call. 这一切都在主线程中完成,但是无论如何我还是尝试将其分派到主线程进行reloadData调用。 That made no difference. 没关系。 I tried tableView.layoutIfNeeded() after reloadData and that also made no difference. 我在reloadData之后尝试了tableView.layoutIfNeeded(),这也没有任何区别。

Placing break points in the cellForRowAtIndexPath and heightForRow... methods indicate normal tableView calls as expected at each pass in the loop. 将断点放置在cellForRowAtIndexPath和heightForRow ...方法中可指示正常的tableView调用,如循环中的每个遍历所预期的那样。 However for some reason the cells don't draw on screen until the loop is completed. 但是由于某种原因,直到循环完成,单元格才会在屏幕上绘制。

Is there anyway to force the tableView to draw the cell at each pass other than what I have tried above? 无论如何,除了我上面尝试过的以外,是否有迫使tableView在每次通过时绘制单元格的方法?

我相信原因是因为元素的循环将很快完成(毫秒),因此您不会注意到增量更改。

You need to run outer loop in global queue like below and dispatch reloadData to main queue. 您需要像下面这样在全局队列中运行外循环,并将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 )
        }
    }
}

If you want a neat animation thats visible then you can probably force a timer on it, between each append; 如果您希望看到一个整洁的动画,那么您可以在每个追加之间强制设置一个计时器。 with a UIView.animate or UIView.transition... I'd prefer the transition method, it gives you a few options that make your changes even neater. 使用UIView.animate或UIView.transition ...我更喜欢transition方法,它为您提供了一些使更改更整洁的选项。

Here is a sample of what you can do (dont copy paste it directly, adjust it to your own, i wrote it in playground without testing it) 这是您可以做的事的示例(不要直接复制粘贴,请调整为自己的样式,我是在操场上编写的,未经测试)

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()
    }
}

Other than that, you can change the content mode of your tableView (most probably from the storyboard) to be set to .top so on every change your tableView keeps on sticking to the top rather than jumping around ( https://developer.apple.com/documentation/uikit/uiview/1622619-contentmode ). 除此之外,您可以将tableView的内容模式(很可能是从情节.top更改)设置为.top以便每次更改时tableView都保持在顶部而不是四处移动( https://developer.apple .com / documentation / uikit / uiview / 1622619-contentmode )。 This specially helps if you're using autolayouts 如果您使用自动版式,这特别有用

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

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