dispatch_get_main_queue() 在从一个 ViewController 移动到另一个 ViewController 并再次返回时不更新 UI

dispatch_get_main_queue() not update UI when move from oneViewController to another ViewController and back again

在我的应用程序中,我在后台执行长任务。所以我使用 Grand Central Dispatch (GCD) 并更新主队列中的 UI 。

这是我的代码

dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_BACKGROUND.value), 0), {
    // perform long task
    //update UI   
     dispatch_async(dispatch_get_main_queue(), {
           self.Label.text = "value changed"  // not work
           self.collectionView.reloadData() // work properly
        })    
})  

它将正常工作。但是,当我从当前的 ViewController 移动到 NextViewController 并再次返回到 ViewController 时,后台任务被执行但我的 Label 不会改变。

问题:请帮助我,这样我就可以在从另一个 ViewController

回来时更新我的​​ UI

注意: 将一个 ViewController 移动到另一个任务在主队列中执行。

编辑: 这是@Yuri 代码的输出

2015-06-08 14:34:19.565 myApp[7726:1481939]  before: self:Logic() `self.label:<myApp.ViewController: 0x15947e00>

2015-06-08 14:34:50.925 myApp[7726:1481925]  after: self:Logic() self.label:<myApp.ViewController: 0x15947e00>`  

Edit2 这是@Oyeoj

的输出
before: <UILabel: 0x16565c60; frame = (20 56; 104 18); text = 'Back up'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x16565eb0>>
after: <UILabel: 0x16565c60; frame = (20 56; 104 18); text = 'value changed'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x16565eb0>>

查看指针,是否相同?

我的 be 块从未调用过?

NSLog(@"%s before: self:%@ self.label:%@", __PRETTY_FUNCTION__, self, self.Label);
dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_BACKGROUND.value), 0), {
       // perform long task
       //update UI   
       dispatch_async(dispatch_get_main_queue(), {
          self.Label.text = "value changed"
          NSLog(@"%s after: self:%@ self.label:%@", ____PRETTY_FUNCTION__, self, self.Label);        
       })    
})

UI 的更新必须在主线程中进行,您在 UI 中的更新很可能不起作用..

试试这个:

dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_BACKGROUND.value), 0), {

    dispatch_async(dispatch_get_main_queue(), {

         println("before: \(self.Label)")

         self.collectionView.reloadData() 

         self.Label.text = "value changed"

         self.Label.setNeedsDisplay() // don't forget this line..

         println("after: \(self.Label)")
    })    
})  

编辑 1

好的,我投了反对票,我至少可以知道为什么吗?只是为了我的启迪,谢谢..

从你的@edit2 日志来看,self.Label.text 的值似乎已更新,但你的 UIViewController 不受主线程的控制..

我会建议您使用 NSNotificationCenter 来触发您的更新 ViewController

现在看起来像这样:

NSNotificationCenter.defaultCenter().addObserver(self, selector: "methodReceiver:", name:"NotificationIdentifier", object: nil)

dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_BACKGROUND.value), 0), {
    //long task
    dispatch_async(dispatch_get_main_queue(), {

         // sends notification to `methodReceiver` 
        NSNotificationCenter.defaultCenter().postNotificationName("NotificationIdentifier", object: nil)
    })    
})

@objc func methodReceiver(notification: NSNotification){

    dispatch_async(dispatch_get_main_queue(), {

        self.collectionView.reloadData() 

        self.Label.text = "value changed"

        self.Label.setNeedsDisplay() // don't forget this line..

    })


    // in case you want to remove the Observer after notification was delivered 
    NSNotificationCenter.defaultCenter().removeObserver(self, name: "NotificationIdentifier", object: nil)
}

希望这出于某种原因对您有所帮助..

编辑 2

来自评论: this approach is work , but i want to know why my UIViewController is not in controll of main thread

在你的

里面

dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_BACKGROUND.value), 0)

您正在后台处理(长任务)并且不会阻塞任何主线程activity...

然后您更改为 AnotherUIViewController,其中有 UI 更新,现在您的主线程在 AnotherUIViewController 的控制之下,而 dispatch_async(dispatch_get_global_queue( 仍在进行中,那么让我们假设你回到 UIViewController 然后 dispatch_async(dispatch_get_main_queue(), { 被解雇了,但是 AnotherUIViewController 里面的任务还没有完成,

例如:

[self.navigationController popViewControllerAnimated:YES]; // -> (in objective-C code)

或任何其他 UI 当前正在进行的更新将在 UIViewController 再次控制主线程之前首先处理,因为所有调度队列都是 FIFO..

我相信这就是它的工作原理..

有关此内容的更多信息,请参阅来自苹果的 Grand Central Dispatch (GCD) Reference..