【问题标题】:Progress Indicator does not animate进度指示器没有动画
【发布时间】:2016-01-08 02:07:11
【问题描述】:

我设置了一个标签和一个进度指示器来绑定到 AppDelegate 的 progress 属性。然后我在并发队列上执行工作。随着每项任务的完成,我将进度增加 1。

我的问题是标签按预期逐个更新,但进度指示器没有。它每 15 个滴答声左右更新一次。知道如何使进度指示器随每个刻度移动吗?

一个简化的例子:

class AppDelegate: NSObject, NSApplicationDelegate {
    dynamic var progress = 0

    @IBAction func updateProgress(sender : AnyObject) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
            guard self.progress < 100 else {
                return
            }

            self.progress += 1
            sleep(1)
            self.updateProgress(sender)
        }
    }
}

【问题讨论】:

    标签: swift macos swift2 cocoa-bindings


    【解决方案1】:

    根据我的经验,从后台队列更新绑定变量有时会导致有趣的行为。进度指示器未更新就是一个例子。我还没有弄清楚“为什么”部分。我的解决方法是在后台队列上做你的工作,但在主队列上更新绑定变量。

    试试这个(未测试):

    @IBAction func updateProgress(sender : AnyObject) {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
            guard self.progress < 100 else {
                return
            }
    
            dispatch_async(dispatch_get_main_queue()) {
                self.progress += 1
            }
    
            sleep(1)
            self.updateProgress(sender)
        }
    }
    

    我注意到您的并发队列在示例中不是并发的。我假设您使用后台线程一次执行多个任务。如果是这样,增加主队列的进度也有助于解决竞争条件,因为主队列是串行的,所以所有的进度增量都是一个接一个地执行的。

    【讨论】:

      【解决方案2】:

      对 UI 的更改应该在主线程上更新。您应该将更新进度移至主线程。

      dispatch_async(dispatch_get_main_queue()) {
          self.updateProgress(sender)
      }
      

      【讨论】:

      • 感谢您的回复。我使用 Cocoa 绑定的原因是利用 KVO 一次更新多个控件。为什么它适用于一个控件而不适用于另一个?
      • 我认为你可以阅读这个stackoverflow.com/questions/12693197/…
      • 这是一个糟糕的建议。如果updateProgress 需要很长时间才能完成,它将锁定您的主队列并冻结您的 UI。
      猜你喜欢
      • 2018-10-19
      • 2015-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-10
      • 1970-01-01
      相关资源
      最近更新 更多