2017-03-21 5 views
1

NSProgress에 문제가 있습니다. 문제는 NSProgressIndicator이 프로세스 중에 업데이트되지 않고 프로세스 완료시 작은 완료된 부분 만 표시한다는 것입니다. localizedDescription은 프로세스가 끝날 때만 표시되지만 100 % 완료되었습니다.NSProgressIndicator를 업데이트하는 방법은 무엇입니까?

그래서, 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이 사용하는 하나의 방법 findRepeatsWithProgressReporting와 클래스가 totalUnitCount: 10을 갖는 repeatsProgress.becomeCurrent(withPendingUnitCount: 10)를 사용하여 parentProgress repeatsProgress에 childProgress 같은 방법 findRepeatsWithProgressReporting의 작업을 추가 한 .

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?) 
{ ... 

와 내가 볼의 내부

print("Observed Something") 

을 추가 한

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

인쇄 두 배 "Observed Something" 즉시 시작과 끝에서 여섯 번, 그 사이에 인쇄가 없습니다 (업데이트 프로세스에 필요한 것으로 예상 됨). 그 이유는 무엇일까요?

답변

2

이것은 동시성 문제처럼 보입니다. func actionFindRepeats(_ sender: AnyObject)이 주 스레드에서 실행 중이므로 NSProgressIndicator에 직접 영향을 미치는 UI 업데이트와 동의합니다.

그것에 대해 자세한 내용은 그 대답의 마지막 예를 참조하십시오

당신은 당신의 actionFindRepeats의 모든 콘텐츠가 블록으로 기능하고 작동하는지 확인 추가 시도 할 수 있습니다 : 그 블록

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

참조 :

012,351,641 조언을
+0

감사합니다! 앞서 설명한 작업에 대해서만 테스트 프로젝트를 만들었습니다. 진행보고가있는 문자열에서 반복을 검색했습니다. 모두 AppDelegate에서 수행됩니다. DispatchQueue.global(). async를 제안하면서 추가했습니다. 이제이 프로젝트에서 완료된 NSProgressIndicator와 100 % 완료된 localizedDescription을 프로세스의 마지막에서 확인합니다. 주 프로젝트에서 동일한 작업에 대해 별도의 컨트롤러가 있고 NSProgressIndicator는 여전히 동일합니다. 그리고 두 프로젝트에서 NSProgressIndicator를 업데이트하지 않았으며 중간 비율도 없습니다. – VYT

+0

그리고 두 프로젝트 모두에서 변경 한 후에 테스트 프로젝트에서 다음과 같은 작업을 수행합니다. 2017-03-24 19 : 39 : 55.202 Test2 [3926 : 127626] 커밋되지 않은 CATransaction. CA_DEBUG_TRANSACTIONS = 1을 디버그 환경에 설정하십시오. CoreAnimation : 커밋되지 않은 CATransaction이있는 경고, 삭제 된 스레드. CA_DEBUG_TRANSACTIONS = 1을 backtraces 로그 환경에서 설정하십시오. – VYT

+0

나는 귀하의 조언이 문제의 핵심이라고 생각합니다. 다시 한 번 감사 드리며 귀하의 답변을 수락합니다. – VYT