【问题标题】:NSProgressIndicator not working in El CapitanNSProgressIndicator 在 El Capitan 中不起作用
【发布时间】:2015-10-13 15:55:18
【问题描述】:

我有一个 OS X Swift 应用程序可以在 Yosemite 中正常运行,但进度条在 El Capitan 中没有显示。其他一切在“真实”程序中正常工作。

我创建了一个存根程序来尝试调试问题,但我仍然无法显示进度条。使用 XCode 7.0.1 (7A1001) 从头开始​​创建这个

测试应用接受一个计数器输入(输入)并且应该显示一个进度条,直到达到计数。如果进度条未隐藏,它确实会出现,但直到结束时才会刷新,当它显示为蓝色 100% 时。我添加了progressBar.display() - 没有效果,我得到与window.display() 相同的效果,即没有变化。

progCount 是我放在窗口上的另一个字段,以查看是否可以看到数字在增加,但直到最后一个数字才显示。

我使用 debug 并看到 i 值上升,progressBar.doubleValue 也增加了。它看起来像一个窗口重绘问题,但我找不到不同的方法。还要记住,这适用于优胜美地。

欢迎任何帮助,谢谢

--- 代码片段----

@IBOutlet weak var window: NSWindow!
@IBOutlet weak var progressBar: NSProgressIndicator!
@IBOutlet weak var counter: NSTextField!
@IBOutlet weak var progCount: NSTextField!

//(a bit of housekeeping not shown)

@IBAction func countUp (sender: NSButton) {
    var i=0

    if counter.integerValue != 0 {
        progressBar.hidden = false
        progressBar.minValue = 0.0
        progressBar.doubleValue = 0.0
        progressBar.maxValue = counter.doubleValue

        while i < counter.integerValue {
            i=i+1
            progressBar.incrementBy(1.0)    
            progCount.doubleValue = progressBar.doubleValue
        }
        progressBar.hidden = true

    }
}

---结束---

【问题讨论】:

    标签: macos swift osx-elcapitan


    【解决方案1】:

    发现自己处于相同的情况,因为我正在从主线程上的紧密循环中更新我的 NSProgressIndicator。 在 El Capitan 之前,我只是在窗口上调用displayIfNeeded,进度指示器就在其中,它运行良好。使用 El Capitan 时,这会发生故障,进度指示器卡在 0%。 虽然我同意重写我的循环以在后台线程上运行并调用主线程以更新进度指示器将是最好的解决方案,但不幸的是,这不是我的选择。

    所以我想出的解决方法是首先在窗口上调用displayIfNeeded,然后 [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.001]];

    这给了主运行循环一些时间来呼吸,进度指示器正确前进。 是的,这是一种 hack,但在 GUI 应用程序的主线程上运行紧密循环也是如此。

    【讨论】:

    • 我已经应用了您的解决方法,我确认它也可以解决 macOS Sierra 中的类似情况:github.com/gui-dos/Guigna/blob/…
    • 可以确认这也适用于工作表。 (我正在使用一张表格来记录一个长时间运行的解析操作的进度。)感觉很难看,我希望 Apple 会有所缓解,但它确实可以解决问题。谢谢。
    【解决方案2】:

    我无法解释为什么您的应用在 Yosemite 和 El Capitan 上的运行方式可能不同,但从您共享的代码的角度来看,您所描述的是它的预期行为。这是由于countUp 函数中的代码立即有效地达到了它们的最终值。这些是您可以看到的值。为了能够看到中间值,需要调整更新的时间。

    为了说明如何观察延迟更新,可以添加延迟,如下修改:

    while i < counter.integerValue {
        i=i+1
    
        let delay = Double(i) * 1.0 * Double(NSEC_PER_SEC)
        let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
    
        dispatch_after(time, dispatch_get_main_queue()) {
            progressBar.incrementBy(1.0)    
            progCount.doubleValue = progressBar.doubleValue
          }
    }
    

    延迟使得第一次更新立即发生,第二次更新在 1 秒后发生,第三次更新在第一次更新后 2 秒发生,依此类推,更新被安排在主线程的串行调度队列中,适合 UI 更新的那个。

    【讨论】:

    • 谢谢。在 Apple Developer board 上,另一位开发人员已经用 Objective C 程序验证了 El Capitan 上的 NSProgressIndicator 和 Yosemite 之间的区别。看起来像是某处的操作系统错误......
    • 不客气。这是一个有趣的错误。我希望它得到解决,并且当它解决时您会在此处记下它。
    • 抱歉更新缓慢。我仍然无法通过 Daniel Zhang 的添加来完成这项工作,但现在通过 despatch_after 构造中的 self.window.display() 实现了这一点。
    【解决方案3】:

    尝试在进度条的编辑器中勾选“可以同时绘制”。虽然它可能不是真正的解决方案,但这可能会作为一种解决方法来解决问题。

    【讨论】:

      猜你喜欢
      • 2016-01-25
      • 2016-03-03
      • 1970-01-01
      • 1970-01-01
      • 2017-01-28
      • 1970-01-01
      • 2016-10-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多