【问题标题】:Cannot update UI in main thread with didSet swift无法使用 didSet swift 在主线程中更新 UI
【发布时间】:2020-01-17 11:59:22
【问题描述】:

我正在尝试在主线程中更新 UILabel 和 UIImageView 但它不起作用。

我有两个 ViewControllers(我在这里称它们为 ChooseCountryVC 和 DisplayCountryVC),在 ChooseCountryVC 中,用户可以选择他们喜欢的国家,在 DisplayCountryVC 中,我想在标签中显示国家名称,并在 imageView 中显示国家标志。

基本流程如下。

  1. 在 DisplayCountryVC 中点击“选择国家”按钮
  2. 现在的ChooseCountryVC基本上是所有国家的tableView,用户可以选择一个国家
  3. 当用户选择国家时,在 DisplayCountryVC 中设置名为“countryCode”的属性并关闭 ChooseCountryVC 以返回 DisplayCountryVC
  4. 在 DisplayCountryVC 中“countryCode”的 didSet 函数中,将 UI 更新过程添加到主线程。

与此相关的代码示例如下。

●选择国家VC

       // when user has chosen a country and dismiss this VC
        let displayCountryVC = DisplayCountryVC()
        displayCountryVC.countryCode = self.chosenCountryCode
        self.dismiss(animated: true, completion: nil) // go back to DisplayCountryVC

●DisplayCountryVC

 var countryCode: String? {
    didSet {
        guard let countryCode = countryCode else {return}
        let countryName = self.getCountryName(with: countryCode) // this function provides countryName with no problem
        let flagImage = self.getFlag(with: countryCode) // this function provides flag image with no problem
        DispatchQueue.main.async {
            self.imageView.image = flagImage 
            self.label.text = countryName
            print("label's text is", self.label.text) // somehow, this prints out country's name correctly in console but apparently UI has not been updated at all
        }
    }
}

如果有人知道我的代码有什么问题或需要更多信息,请告诉我。

【问题讨论】:

  • DispatchQueue.main.async 在这里不是必需的。分配displayCountryVC.countryCode 时,您仍在主线程中。您如何展示您的 DisplayCountryVC?你在表演segue吗?确保 flagImagecountryName 不为零
  • @tuyen 谢谢你的评论。起初我就是这么想的,所以我写了一个没有 DispatchQueue.main.async 的代码,但它没有用,所以我添加了它。此外,DisplayVC 是初始视图控制器,当用户点击 VC 中的按钮时,我会以编程方式使用当前函数呈现 ChooseCountryVC。我确保 flagImage 和 countryName 不为零,但仍然没有显示在视图中。
  • 如果没有DispatchQueue.main.async,那么didSet就没有被执行?以及为什么在提交DisplayCountryVC 之后dismiss ChooseCountryVC。有什么原因吗?
  • @tuyenle didSet 在没有DispatchQueue.main.async 的情况下执行,如果我在 didSet 闭包中打印标签的文本,它会在控制台中打印正确的字符串,但不会在视图上打印
  • 如果它在控制台中打印出正确的字符串,那么您会在视图中看到什么文本?

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


【解决方案1】:
 // when user has chosen a country and dismiss this VC
        let displayCountryVC = DisplayCountryVC()
        displayCountryVC.countryCode = self.chosenCountryCode
        self.dismiss(animated: true, completion: nil) // go back to DisplayCountryVC

在这里你初始化一个新的视图控制器并设置它的值。

您的 selectedCountryCode 设置为新的视图控制器,而不是您原来的 DisplayCountryVC。

在您的 ChooseCountryVC 关闭后,您将返回到原来的 DisplayCountryVC。这个新的 DisplayCountryVC 没有被展示或使用。

您需要编写一个委托或回调来将所选国家代码传递给您原来的 DisplayCountryVC。

【讨论】:

  • 哦,我完全忘记了我是在拒绝原来的 VC 没有展示它!多亏了这个,我解决了这个问题。非常感谢你:)
猜你喜欢
  • 1970-01-01
  • 2017-05-23
  • 1970-01-01
  • 1970-01-01
  • 2018-06-14
  • 2022-01-16
  • 2013-05-05
  • 1970-01-01
相关资源
最近更新 更多