NSProgress is a useful class for tracking progress across queues. It relies on observing the "fractionCompleted" property. But when/how are you supposed to remove the observer? I tried dispatch_group and dispatch_barrier but the observer is still removed before all the work has been completed.
This is the code I have so far.
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
}
}
}