【问题标题】:Unexpected layout behaviors without DispatchQueue.main.async没有 DispatchQueue.main.async 的意外布局行为
【发布时间】:2018-11-06 22:31:05
【问题描述】:

有时当自动布局或 UI 更改没有按照我的意愿执行时,我将代码包装到 DispatchQueue.main.async 中并得到解决(例如):

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)
    DispatchQueue.main.async {
        self.tableview.reloadData()
    }
}

但是用 (Thread.current) 调试这段代码而没有 DispatchQueue 它告诉我它已经在主线程中但它不能很好地完成动画,只需添加 DispatchQueue.main.async 就可以了。我想知道DispatchQueue.main.async 到底是什么使它起作用。因为我认为它只是让代码在主线程中执行,但如果它已经在主线程中执行,它不应该做任何事情......但是这样它就可以正常工作并且不会产生布局问题。

(我遇到过不同的代码和不同的应用程序,我一直在调试并告诉我已经在主线程中)。

我认为这可能是因为 dispatchQueue 产生了一点延迟,但它在更多不需要延迟的地方发生在我身上(Swift Animate duration not working in CGAffineTransform -> 今天我在没有 dispatchMainQueue 的情况下调试了这个问题,它正在也在主线程中执行,但没有调度它就无法工作)

【问题讨论】:

  • 您是在真实设备上进行测试,对吧?您不应该在模拟器上测试线程。此外,如果没有看到您从哪个上下文调用 tableView.reloadData,很难判断该代码是否确实应该已经在主线程上运行。
  • 简单来说,当你使用 DispatchQueue.main.async 时,self.tableview.reloadData() 会在一小段延迟后被调用(因为块会在下一个循环中执行)。这就是你与众不同的原因。
  • 我已经更新了我的问题,以检查代码是否已经在主线程中运行,我正在打印 Thread.current,它告诉我我在主线程中并检查断点。
  • @trungduc 在延迟不影响stackoverflow.com/questions/50547386/… 的情况下发生在我身上(在这篇文章中,我还调试了动画在主线程中执行而没有添加 DispatchQueue。主要)
  • @DávidPásztor 是的,我在真机上测试(另外,我之前回复过你,没提你)

标签: ios swift multithreading user-interface grand-central-dispatch


【解决方案1】:

简单地说,当你使用DispatchQueue.main.async 时,self.tableview.reloadData() 将在一个小的延迟后被调用(因为块将在下一个循环中执行)。这就是你与众不同的原因。

在这种情况下,viewWillTransition(to:with:) 在设备将旋转时执行。这意味着此时可能有问题并且设备尚未旋转。所以如果你调用self.tableview.reloadData(),它可能会给出错误的结果。

为什么DispatchQueue.main.async 解决了这个问题? - 这是因为DispatchQueue.main.async 在块执行之前给出了一个延迟,并且有了这个延迟,self.tableview.reloadData() 将在设备完成旋转后被调用。这就是为什么它给出正确的结果

使用animate(alongsideTransition:completion:) 即可,您无需使用DispatchQueue.main.async

override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
  coordinator.animate(alongsideTransition: nil, completion: { (_) in
    self.tableview.beginUpdates()
    self.tableview.endUpdates()
  })
}

【讨论】:

  • 我会尝试让你知道,(但是,在延迟不影响stackoverflow.com/questions/50547386/… 的情况下,我已经发生了这种情况(在这篇文章中,我还调试了动画在没有添加 DispatchQueue.main 的情况下在主线程中执行)
  • 我已经尝试过这个解决方案,但它不断做出意想不到的布局行为:(
  • 我的回答重点是当前问题。对于您的其他问题,您应该提供足够的信息来调用方法。我尝试了您问题中的代码,它在不使用 DispatchQueue.main.async 的情况下正常工作
  • 您能解释一下这种意外的布局行为吗?
  • 完成! (另外,如果改为添加tableview.reload数据,你使用beginUpdates和endUpdates,它会使动画更流畅)
猜你喜欢
  • 2017-09-19
  • 2021-09-18
  • 2016-05-27
  • 2016-05-11
  • 1970-01-01
  • 2021-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多