2017-03-21 74 views
1

我有問題NSProgress。問題是NSProgressIndicator在此過程中沒有更新,並且在過程結束時只顯示一小部分已完成部分。 localizedDescription也僅在流程結束時顯示,但已完成100%。如何更新NSProgressIndicator?

所以,我有一類具有使用一種方法findRepeatsWithProgressReportingNSProgress

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() 
    } 
} 

最後一部分是志願:

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"立即在開始之後和最後6次之間,沒有打印之間(因爲它預計將用於更新過程)。可能是什麼原因?

回答

2

這看起來像是一個併發問題。由於func actionFindRepeats(_ sender: AnyObject)正在主線程中運行,因此它與UI更新一致,這會直接影響NSProgressIndicator

見這個答案的最後一個例子爲更多細節是:

你可以嘗試添加您actionFindRepeats的所有內容功能成塊,看看它的工作原理:

DispatchQueue.global().async { 
    // qos' default value is ´DispatchQoS.QoSClass.default` 
} 

參考該塊:

+0

謝謝你的建議!我只爲上述任務做了一個測試項目,在進行報告的字符串中搜索重複項。全部在AppDelegate中完成。我已經按照你的建議DispatchQueue.global()。async添加了,現在在這個項目中,我看到完成了NSProgressIndicator,並且在該過程結束時完成了100%完成的localizedDescription。在主項目中,我爲相同的任務分開了Controller,但仍然是不完整的NSProgressIndicator。而且,在這兩個項目中,我沒有更新NSProgressIndicator,也沒有中間百分比。 – VYT

+0

現在在兩個項目中,在我做出的更改之後,我還在測試項目中進行了以下測試:2017-03-24 19:39:55.202 Test2 [3926:127626] Uncommited CATransaction。在要調試的環境中設置CA_DEBUG_TRANSACTIONS = 1。 CoreAnimation:警告,用未提交的CATransaction刪除線程;在環境中設置CA_DEBUG_TRANSACTIONS = 1以記錄回溯。 – VYT

+0

我發現你的建議是問題的正確答案,所以再次感謝,我接受你的回答。 – VYT