如何更新 NSProgressIndicator?
How to update the NSProgressIndicator?
我对 NSProgress
有疑问。问题是 NSProgressIndicator
在过程中没有更新,并且在过程结束时只显示一小部分完成的部分。 localizedDescription 也仅在流程结束时显示,但已完成 100%。
所以,我有一个 class,其中一种方法 findRepeatsWithProgressReporting
使用 NSProgress
class TestProgress: NSObject, ProgressReporting
{
let progress: Progress
override init()
{
progress = Progress()
super.init()
}
func findRepeatsWithProgressReporting(stringToSearch: String, minimalLength: Int, maximalLength: Int) -> [String]
{
var arrayOfRepeats = [String]()
progress.totalUnitCount = Int64((minimalLength...maximalLength).count)
for i in minimalLength...maximalLength
{
let arrayOfStrings = stringToSearch.chopString(stringOut: stringToSearch, length: i)
let arrayOfUniqueStrings = Array(Set(arrayOfStrings))
for each in arrayOfUniqueStrings
{
let arrayOfNSRanges = stringToSearch.searchForNSRangesOfStringInString(stringOut: stringToSearch, stringIn: each)
var positions = String()
if arrayOfNSRanges.count > 1
{
for each1 in arrayOfNSRanges
{
let repeatStart = String(each1.location + 1)
let repeatEnd = String(each1.location + each1.length)
positions += "(" + repeatStart + "-" + repeatEnd + ")"
}
let stringToShow = each + " " + positions
arrayOfRepeats.append(stringToShow)
}
}
progress.completedUnitCount += 1
}
return arrayOfRepeats
}
}
然后,在 myVewContrloler
中,我有 parentProgress repeatsProgress
具有 totalUnitCount: 10
并将方法 findRepeatsWithProgressReporting
的任务作为 childProgress 添加到 parentProgress repeatsProgress
使用 repeatsProgress.becomeCurrent(withPendingUnitCount: 10)
。
private var progressObservationContext = 0
class myVewContrloler: NSViewController
{
...
var testProgress = TestProgress ()
var repeatsProgress = Progress()
@IBOutlet weak var repeatsSearchProgressBar: NSProgressIndicator!
@IBOutlet weak var repeatsPercentText: NSTextField!
@IBOutlet weak var minimalLength: NSTextField!
@IBOutlet weak var maximalLength: NSTextField!
@IBOutlet var foundRepeats: NSTextView!
@IBAction func actionFindRepeats(_ sender: AnyObject)
{
repeatsProgress = Progress(totalUnitCount: 10)
let options : NSKeyValueObservingOptions = [.new, .old, .initial, .prior]
repeatsProgress.addObserver(self, forKeyPath: "fractionCompleted", options: options, context: &progressObservationContext)
repeatsProgress.addObserver(self, forKeyPath: "localizedDescription", options: options, context: &progressObservationContext)
var arrayOfRepeats = [String]()
repeatsProgress.becomeCurrent(withPendingUnitCount: 10)
arrayOfRepeats = testProgress.findRepeatsWithProgressReporting(stringToSearch: stringToSearch, minimalLength: minimalLength.integerValue, maximalLength: maximalLength.integerValue)
...
repeatsProgress.removeObserver(self, forKeyPath: "fractionCompleted")
repeatsProgress.removeObserver(self, forKeyPath: "localizedDescription")
repeatsProgress.resignCurrent()
}
}
最后一部分是针对 KVO 的:
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?)
{
guard context == &progressObservationContext else {
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
return
}
if keyPath == "fractionCompleted"
{
OperationQueue.main.addOperation{
let progress = object as! Progress
self.repeatsSearchProgressBar.doubleValue = progress.fractionCompleted
self.repeatsPercentText.stringValue = progress.localizedDescription
}
}
}
我已经添加了
print("Observed Something")
在
里面
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?)
{ ...
我看到的是 "Observed Something"
在开始后立即打印两次,在结束时打印六次,中间没有打印(正如更新过程所预期的那样)。可能是什么原因?
这似乎是一个并发问题。由于 func actionFindRepeats(_ sender: AnyObject)
在主线程中是 运行,它与 UI 更新同时发生,这直接影响 NSProgressIndicator
。
有关详细信息,请参阅该答案的最后一个示例:
您可以尝试将 actionFindRepeats 函数的所有内容添加到该块中,看看它是否有效:
DispatchQueue.global().async {
// qos' default value is ´DispatchQoS.QoSClass.default`
}
该块的参考:
我对 NSProgress
有疑问。问题是 NSProgressIndicator
在过程中没有更新,并且在过程结束时只显示一小部分完成的部分。 localizedDescription 也仅在流程结束时显示,但已完成 100%。
所以,我有一个 class,其中一种方法 findRepeatsWithProgressReporting
使用 NSProgress
class TestProgress: NSObject, ProgressReporting
{
let progress: Progress
override init()
{
progress = Progress()
super.init()
}
func findRepeatsWithProgressReporting(stringToSearch: String, minimalLength: Int, maximalLength: Int) -> [String]
{
var arrayOfRepeats = [String]()
progress.totalUnitCount = Int64((minimalLength...maximalLength).count)
for i in minimalLength...maximalLength
{
let arrayOfStrings = stringToSearch.chopString(stringOut: stringToSearch, length: i)
let arrayOfUniqueStrings = Array(Set(arrayOfStrings))
for each in arrayOfUniqueStrings
{
let arrayOfNSRanges = stringToSearch.searchForNSRangesOfStringInString(stringOut: stringToSearch, stringIn: each)
var positions = String()
if arrayOfNSRanges.count > 1
{
for each1 in arrayOfNSRanges
{
let repeatStart = String(each1.location + 1)
let repeatEnd = String(each1.location + each1.length)
positions += "(" + repeatStart + "-" + repeatEnd + ")"
}
let stringToShow = each + " " + positions
arrayOfRepeats.append(stringToShow)
}
}
progress.completedUnitCount += 1
}
return arrayOfRepeats
}
}
然后,在 myVewContrloler
中,我有 parentProgress repeatsProgress
具有 totalUnitCount: 10
并将方法 findRepeatsWithProgressReporting
的任务作为 childProgress 添加到 parentProgress repeatsProgress
使用 repeatsProgress.becomeCurrent(withPendingUnitCount: 10)
。
private var progressObservationContext = 0
class myVewContrloler: NSViewController
{
...
var testProgress = TestProgress ()
var repeatsProgress = Progress()
@IBOutlet weak var repeatsSearchProgressBar: NSProgressIndicator!
@IBOutlet weak var repeatsPercentText: NSTextField!
@IBOutlet weak var minimalLength: NSTextField!
@IBOutlet weak var maximalLength: NSTextField!
@IBOutlet var foundRepeats: NSTextView!
@IBAction func actionFindRepeats(_ sender: AnyObject)
{
repeatsProgress = Progress(totalUnitCount: 10)
let options : NSKeyValueObservingOptions = [.new, .old, .initial, .prior]
repeatsProgress.addObserver(self, forKeyPath: "fractionCompleted", options: options, context: &progressObservationContext)
repeatsProgress.addObserver(self, forKeyPath: "localizedDescription", options: options, context: &progressObservationContext)
var arrayOfRepeats = [String]()
repeatsProgress.becomeCurrent(withPendingUnitCount: 10)
arrayOfRepeats = testProgress.findRepeatsWithProgressReporting(stringToSearch: stringToSearch, minimalLength: minimalLength.integerValue, maximalLength: maximalLength.integerValue)
...
repeatsProgress.removeObserver(self, forKeyPath: "fractionCompleted")
repeatsProgress.removeObserver(self, forKeyPath: "localizedDescription")
repeatsProgress.resignCurrent()
}
}
最后一部分是针对 KVO 的:
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?)
{
guard context == &progressObservationContext else {
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
return
}
if keyPath == "fractionCompleted"
{
OperationQueue.main.addOperation{
let progress = object as! Progress
self.repeatsSearchProgressBar.doubleValue = progress.fractionCompleted
self.repeatsPercentText.stringValue = progress.localizedDescription
}
}
}
我已经添加了
print("Observed Something")
在
里面override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?)
{ ...
我看到的是 "Observed Something"
在开始后立即打印两次,在结束时打印六次,中间没有打印(正如更新过程所预期的那样)。可能是什么原因?
这似乎是一个并发问题。由于 func actionFindRepeats(_ sender: AnyObject)
在主线程中是 运行,它与 UI 更新同时发生,这直接影响 NSProgressIndicator
。
有关详细信息,请参阅该答案的最后一个示例:
您可以尝试将 actionFindRepeats 函数的所有内容添加到该块中,看看它是否有效:
DispatchQueue.global().async {
// qos' default value is ´DispatchQoS.QoSClass.default`
}
该块的参考: