从ViewController函数循环中更新NSProgress显示

时间:2017-06-08 13:02:30

标签: swift redraw nsprogress

我又回到了Hive Mind!

在我的ViewController类中,我有一个迭代数组中一系列项的函数。我想要发生的是在循环的每次迭代中更新我的进度条,但看起来它不会更新屏幕上的进度条,直到它完成整个循环并退出我的函数。

我很确定这只是因为每次通过应用程序循环只会重新绘制一次视图(我可能在这里没有使用正确的术语。)

当我还在ViewController函数循环中时,强制ViewController视图更新的正确方法是什么?

这基本上就是我现在正在做的事情:

func myFunction() {
     for item in collection {
         progressBar.increment(by:1)
         progressBar.display()
     }
     // execute my other code
}

当这不起作用时,我尝试在progressBar.draw方法之后添加一个needsSetDisplay,如下所示:

func myFunction() {
     for item in collection {
         progressBar.increment(by:1)
         progressBar.display()
         let rect = self.view.visibleRect
         self.view.needsSetDisplay(rect)
     }
     // execute my other code
}

但它仍然没有用。

我确信有一种方法可以完成我需要做的事情,但我怀疑它涉及一些更高级的东西,例如运行多个进程,我可能没有资格做的事情因为我是新手对于斯威夫特来说,自从我用Obj-C编写代码已经至少10年了(我忘了我所知道的大部分内容。)

谢谢!

编辑我尝试失败的另一件事是调用progressBar.displayAsNeeded(),但它似乎也没有用。

1 个答案:

答案 0 :(得分:2)

假设您正在主线程上运行,那么您将阻塞,直到该方法完成。无论哪种“需要”样式方法(setNeedsDisplay,displayAsNeeded等),您尝试使用实际的重新显示,直到方法完成后才会发生(显示更新后的分组以避免不断更新)。

你可以做的是将工作放到后台线程上,然后将UI更新重新放回到主线程上,类似于:

DispatchQueue.global(qos: .background).async {
    for item in collection {
        DispatchQueue.main.async {
            progressBar.increment(by:1)
            progressBar.display()
        }
    }
}

当然,这会引发其他问题,例如用户现在可以在后台线程处理时与UI进行交互,而您需要考虑这些问题。

如果您已经在后台线程中运行,那么您只需将进度条更新发送到主线程。