【问题标题】:Update NSProgress display from within ViewController Function Loop从 ViewController 函数循环中更新 NSProgress 显示
【发布时间】:2017-06-08 13:02:29
【问题描述】:

我又回来了蜂巢思维!

在我的 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
}

但还是不行。

我确信有一种方法可以完成我需要做的事情,但我怀疑它涉及一些更高级的事情,例如运行多个进程,我可能还没有资格做这件事,因为我是新手到 Swift,距离我用 Obj-C 编码已经至少 10 年了(也就是我忘记了我所知道的大部分内容。)

谢谢!

编辑我尝试的另一件事是致电progressBar.displayAsNeeded(),但它似乎也不起作用。

【问题讨论】:

  • 你知道你的函数在哪个线程上运行吗?你可以在你的函数中设置一个断点,并在你的断点被命中时检查它在 Xcode 左侧运行的线程。如果它不是主线程(线程 1),那么这很可能是您的问题,因为所有 UI 更新都将在主线程上运行。要解决这个问题,请查看DispatchQueue.main.async

标签: swift redraw nsprogress


【解决方案1】:

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

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

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

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

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

【讨论】:

  • 我没有明确告诉该方法在任何特定线程上运行,所以我假设它在主线程上运行。 (尚未阅读过有关使用多个线程的内容,也从未故意对其进行过任何操作。)您所说的证实了我对屏幕何时更新的怀疑。我将阅读 DispatchQueue 并确认它解决了我的问题。谢谢!
  • 这解决了栏更新的问题。正如您所提到的,因此我还需要清理其他一些问题,但这是另一个帖子的问题。谢谢!
猜你喜欢
  • 2013-01-31
  • 2022-08-15
  • 2016-02-14
  • 2021-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多