0

NSProgress는 큐 전체에서 진행 상황을 추적하는 데 유용한 클래스입니다. 그것은 "fractionCompleted"속성을 관찰하는 것에 의존합니다. 그러나 언제/어떻게 옵저버를 제거해야합니까? dispatch_group 및 dispatch_barrier를 시도했지만 모든 작업이 완료되기 전에 옵저버가 여전히 제거되었습니다.관찰자를 제거 할 NSProgress

이것은 내가 지금까지 가지고있는 코드입니다.

override func observeValueForKeyPath(keyPath: String!, 
    ofObject object: AnyObject!, 
    change: [NSObject : AnyObject]!, 
    context: UnsafeMutablePointer<Void>) 
{ 
    if keyPath == "fractionCompleted" 
    { 
     progressBar.doubleValue = (object as NSProgress).fractionCompleted 
     println((object as NSProgress).localizedDescription) 
    } 
    else 
    { 
     super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context) 
    } 
} 


var overallProgress : NSProgress? 
@IBAction func start(sender: AnyObject) 
{ 
    overallProgress = NSProgress(totalUnitCount: 100) 
    overallProgress?.cancellable = true 
    overallProgress?.cancellationHandler = {() ->() in 
     println("cancelled") 
    } 
    overallProgress?.addObserver(self, 
     forKeyPath: "fractionCompleted", 
     options: (.Initial | .New), 
     context: nil) 

    var dispatchGroup = dispatch_group_create() 

    dispatch_group_async(dispatchGroup, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { 


    //dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) 

    { [unowned self] in 

     if !(self.overallProgress?.cancelled ?? false) 
     { 
      self.overallProgress?.becomeCurrentWithPendingUnitCount(50) 
      self.doWork(2) 
      self.overallProgress?.resignCurrent() 
     } 

     if !(self.overallProgress?.cancelled ?? false) 
     { 
      self.overallProgress?.becomeCurrentWithPendingUnitCount(50) 
      self.doWork(1) 
      self.overallProgress?.resignCurrent() 
     } 

    } 

    dispatch_group_notify(dispatchGroup, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)){ 
     dispatch_async(dispatch_get_main_queue()) { 
      println("remove") 
      self.overallProgress?.removeObserver(self, forKeyPath: "fractionCompleted") 
     } 
    } 

    // dispatch_barrier_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { 
//dispatch_async(dispatch_get_main_queue()) { 
//println("remove") 
//self.overallProgress?.removeObserver(self, forKeyPath: "fractionCompleted") 
//   } 
//  } 
} 


@IBAction func cancel(sender: AnyObject) 
{ 
    overallProgress?.cancel() 
} 


func doWork(sleeptime : UInt32) 
{ 
    let privateProgess = NSProgress(totalUnitCount: 5) 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { [unowned self] in 
     for index : Int64 in 0...5 
     { 
      sleep(sleeptime) 
      privateProgess.completedUnitCount = index 
     } 
    } 
} 

답변

1

doWork의 작업은 start에 파견 작업과 같은 dispatch_group에 있지 않습니다. 모든 작업이 완료된 후에 dispatch_group_notify을 실행하려면 doWorkdispatch_group_async을 사용해야 해당 내부 작업을 처리 할 수 ​​있습니다. 그렇지 않으면 doWork에 대한 두 번의 호출이 즉시 반환되고 그룹의 유일한 블록이 완료되어 dispatch_group_notify 블록이 즉시 실행됩니다. 가장 쉬운 방법은 dispatch_group_t을 전달하기 위해 doWork에 매개 변수를 추가하여 해당 그룹의 일부로 내부 작업을 수행 할 수 있도록하는 것입니다.

+0

나는 dispatch_group_t를 전달하고 dispatch_group_enter (작업을 시작하기 전에) 및 dispatch_group_leave (완료 후 작업 기금에서 호출 됨)를 사용하여 그룹의 끝을 알렸다. – user965972