【问题标题】:NSProgress when to remove the observerNSProgress 何时移除观察者
【发布时间】:2014-09-16 23:11:39
【问题描述】:

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
        }
    }
}

【问题讨论】:

    标签: grand-central-dispatch key-value-observing nsprogress


    【解决方案1】:

    doWork 中的工作与您在start 中调度的工作不在同一个dispatch_group。如果您希望在所有工作完成后发生dispatch_group_notify,那么doWork 也需要使用dispatch_group_async 来调度该内部工作。否则,对doWork 的两次调用将立即返回,然后组中的唯一块将完成,导致您的dispatch_group_notify 块立即执行。最简单的方法可能是向doWork 添加一个参数以传入dispatch_group_t,这样内部工作也可以作为该组的一部分完成。

    【讨论】:

    • 我最终传入了 dispatch_group_t 并使用 dispatch_group_enter (开始工作之前)和 dispatch_group_leave (由工作基金调用。完成后)来表示一个组的结束。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-17
    • 2012-01-16
    • 1970-01-01
    • 2014-08-30
    • 1970-01-01
    相关资源
    最近更新 更多