如何使用 UIKit 在 Swift 5 中立即强制更新我的 UI?

How can I force update my UI immediately in Swift 5 using UIKit?

我 运行 我的 UI 有问题,它没有立即更新。

我先打电话给someCustomView.isHidden = false。之后,我创建了一个新 View Controller 的新实例。在新的 VCs viewDidLoad() 中,我正在加载一个 "new Machine Learning Model",这需要一些时间。

private func someFuncThatGetsCalled() {

    print("1")

    self.viewLoading.isHidden = false

    print("2")

    performSegue(withIdentifier: "goToModelVCSegue", sender: nil)

}

只要按下调用此函数的按钮,“1”和“2”就会打印在控制台中。但是,在我的新 VC 的 viewDidLoad() 完成之前,该视图不可见。

是否有可能立即强制更新 UIViewsetNeedsDisplay() 对我不起作用。

感谢您的帮助!

使用layoutIfNeeded()Apple Docs

layoutIfNeeded()

Lays out the subviews immediately, if layout updates are pending. Use this method to force the view to update its layout immediately. When using Auto Layout, the layout engine updates the position of views as needed to satisfy changes in constraints. Using the view that receives the message as the root view, this method lays out the view subtree starting at the root. If no layout updates are pending, this method exits without modifying the layout or calling any layout-related callbacks.

所以根据经验,

layoutifneeded:立即(当前更新周期),同步调用

setNeedsLayout:放松(等到下一个更新周期),异步调用

因此,layoutIfNeeded 表示请立即更新,而 setNeedsLayout 表示请更新,但您可以等到下一个更新周期。

如何使用

yourView.layoutIfNeeded()

你也可以参考图表来更好地记住这些pass的顺序

来源Apple docs on layoutIfNeeded

图片来源 Medium artcle

几个问题...

如果你有一个 "takes some time" 要加载的视图控制器,你不应该尝试以这种方式加载。

该应用程序将无响应并显示 "frozen."

更好的方法是:

  • someFuncThatGetsCalled()
    • 隐藏 viewLoading 并将其替换为 activity 指示器(微调器,或让用户知道应用未卡住的其他东西)
    • 实例化你的ModelVC
    • ModelVC 完成设置后,让它通知当前 VC(通过委托)
    • current VC then 显示/导航到已经实例化和准备好的 ModelVC

或者,可能是更好的选择...将 ModelVC 中耗时的设置移动到 视图出现后 的位置。您可以在 viewDidLoad() 中显示 activity 指标。这确实是最常见的用户体验 - 当新的 VC 必须检索远程数据进行显示时,你会一直看到它 - 它符合用户的期望。