【问题标题】:Is `DispatchQueue.main.async` block in viewWillAppear always called after `viewDidLayoutSubviews`?viewWillAppear 中的 DispatchQueue.main.async 块是否总是在 viewDidLayoutSubviews 之后调用?
【发布时间】:2022-11-17 15:05:01
【问题描述】:

我想在推送 VC 后立即更改集合视图的 contentOffset.x。
所以我在 viewWillAppear 中调用了collectionView.setContentOffset(~)
但由于自动布局循环,它不起作用。

但是,如果我在DispatchQueue.main.async块内调用collectionView.setContentOffset,它就可以工作!

代码如下:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    DispatchQueue.main.async {
        collectionView.setContentOffset(
            CGPoint(x: currentFolderIndex * collectionView.bounds.width), y: 0), 
            animated: false
        )
    }
}

当我打印布局方法的顺序时,我弄清楚了为什么它会起作用。

DispatchQueue.main.async块在viewDidLayoutSubviews之后调用。

它总是这样吗?
为什么它会这样工作?
我很好奇!!

【问题讨论】:

    标签: ios swift viewwillappear dispatch-queue


    【解决方案1】:

    使用async 基本上就是说“有时间就去做”。所以它会在未来不确定的时间(一般不会太久)完成,并且可能在完成当前正在做的事情之后。并且调用函数不会等待主队列上的代码执行完毕才继续。

    因此,在您的情况下,当调用 async 时,UI 线程完成他正在做的事情,调用 viewWillLayoutSubViews,进行自动布局等,...当他完成并有时间时,他异步执行 setContentOffset

    然而,理论上它不能保证它总是相同的顺序:UI 线程可能会在之前找到时间,或者可能被超额预订并且在viewDidAppear之前没有时间......但实际上,我认为你可以安全地假设它会99.99% 的时间都是相同的顺序。

    注意:在其他情况下,你可以考虑使用DispatchQueue.main.sync,它会说“尽快做,我在等你”。但是,这可能是一个糟糕的想法,尤其是当您在 UI 线程中时:您将在 UI 线程中等待 UI 线程执行其他操作,并且您无法摆脱它 - 这是一个死锁。更多详情here

    【讨论】:

      猜你喜欢
      • 2012-10-31
      • 1970-01-01
      • 1970-01-01
      • 2023-04-04
      • 1970-01-01
      • 2014-04-12
      • 1970-01-01
      • 1970-01-01
      • 2017-02-26
      相关资源
      最近更新 更多