ios viewWillAppear中的'DispatchQueue.main.async'块是否总是在'viewDidLayoutSubviews`之后调用?

xuo3flqw  于 2022-11-19  发布在  iOS
关注(0)|答案(1)|浏览(116)

我想在推入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
        )
    }
}

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

viewDidLayoutSubviews之后调用DispatchQueue.main.async块。
总是这样吗?
为什么会这样?
我好好奇啊!!

lrl1mhuk

lrl1mhuk1#

使用async基本上就是说“有时间的时候再做”。所以它将在未来不确定的时间完成(通常不会太久),并且可能在完成当前正在做的事情之后。并且调用函数在继续之前不会等待代码在主队列上执行。
因此,在您的情况下,当调用async时,UI线程完成正在执行的操作,调用viewWillLayoutSubViews,执行自动布局等,...当完成并有时间时,他异步执行setContentOffset
然而,在理论上它并不能保证它永远是同一个顺序:UI线程可以在viewDidAppear之前找到时间,也可以在viewDidAppear之前超额预定而没有时间......但实际上,我认为您可以安全地假设99.99%的时间都是相同的订单。
注意:在其他情况下,您可以考虑使用DispatchQueue.main.sync,它会说“Do it ASAP and I 'm waiting for you”。但是,这可能是一个糟糕的想法,特别是如果您在UI线程中:您将在UI线程中等待UI线程执行其他操作,并且无法退出-这是一个死锁。更多详细信息here

相关问题