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 не в том же dispatch_group как работу, которую вы разослать в start. Если вы хотите, чтобы dispatch_group_notify произошел после завершения всей работы, то doWork необходимо использовать dispatch_group_async для отправки этой внутренней работы. В противном случае два вызова doWork вернутся сразу же, и тогда будет завершен единственный блок в группе, в результате чего ваш блок dispatch_group_notify будет выполнен сразу. Самый простой подход, скорее всего, заключается в добавлении параметра в doWork для передачи в dispatch_group_t, так что внутренняя работа может быть выполнена как часть этой группы.

+0

Я закончил тем, что отправился в dispatch_group_t и использовал dispatch_group_enter (перед началом работы) и dispatch_group_leave (вызванный фондом работы после завершения), чтобы сигнализировать о конце группы. – user965972