我对NSProgress有意见。问题是,NSProgressIndicator没有在过程中进行更新,并且在流程结束时只显示一小部分已完成的部分。localizedDescription也只显示在过程的结束,但作为100%完成。
因此,我有一个类,其中有一个使用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的任务添加到使用repeatsProgress.becomeCurrent(withPendingUnitCount: 10)的parentProgress repeatsProgress中。
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",在结束时打印六次,中间没有打印(这是用于更新过程的预期)。原因是什么?
发布于 2017-03-24 13:08:49
这似乎是一个并发问题。由于func actionFindRepeats(_ sender: AnyObject)在主线程中运行,所以它与UI更新同时进行,这直接影响到NSProgressIndicator。
有关此问题的更多详细信息,请参阅该答案的最后一个示例:
您可以尝试将actionFindRepeats函数的所有内容添加到该块中,并查看它是否有效:
DispatchQueue.global().async {
// qos' default value is ´DispatchQoS.QoSClass.default`
}该区块的参考资料:
https://stackoverflow.com/questions/42916170
复制相似问题