NSProgress是一个用于跟踪队列进度的有用类。它依赖于观察"fractionCompleted"属性。但是,你应该何时/如何移除观察者?我尝试了dispatch_group和dispatch_barrier,但在所有工作完成之前,观察者仍然被删除。
这是我目前掌握的代码。
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
}
}
}
doWork
中的工作与您在start
中调度的工作不在同一个dispatch_group
中。如果您希望dispatch_group_notify
在所有工作完成后发生,那么doWork
也需要使用dispatch_group_async
来调度内部工作。否则,对doWork
的两个调用将立即返回,然后组中唯一的块将完成,从而导致您的dispatch_group_notify
块立即执行。最简单的方法可能是向doWork
添加一个参数以传入dispatch_group_t
,这样内部工作也可以作为该组的一部分来完成。