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
}
}
}
答案 0 :(得分:1)
doWork
中的工作与dispatch_group
中发送的工作不同start
。如果您希望在完成所有工作后发生dispatch_group_notify
,那么doWork
也需要使用dispatch_group_async
来分发内部工作。否则,对doWork
的两次调用将立即返回,然后该组中的唯一一个块将完成,从而导致您的dispatch_group_notify
块立即执行。最简单的方法可能是向doWork
添加一个参数以传递dispatch_group_t
,以便内部工作也可以作为该组的一部分完成。