【问题标题】:Xcode 9 update Swift, purple warningXcode 9 更新 Swift,紫色警告
【发布时间】:2018-03-11 10:28:42
【问题描述】:

不知道为什么在更新到 Xcode 9 后我的项目(最初在 Swift 3 中创建)显示紫色警告: UITextField.text 只能在主线程中使用

如果文本字段为空,我只会检查 If 语句...附上屏幕截图。

【问题讨论】:

标签: ios swift xcode swift4 xcode9


【解决方案1】:

只需添加 DispatchQueue.main.async 即可防止这种情况发生,并在 swift 文档中推荐。

DispatchQueue.main.async { 
    //code that caused error goes here
}

【讨论】:

    【解决方案2】:

    这是关于主线程检查器的 Apple 指南

    • Xcode 9 中的新功能 - 主线程检查器。
      • 启用 UI API 检测 后台线程滥用
      • 检测不是在主线程上进行的 AppKit、UIKit 和 WebKit 方法调用。
      • 在调试过程中自动启用,可以在方案编辑器的“诊断”选项卡中禁用。
      • 主线程检查器适用于 Swift 和 C 语言。

    试试这个:用下面的代码替换你的代码,然后看看。这是一个永久的解决方案,没有禁用警告。

    @IBAction fund saveButtonTapped(_ sender: Any) {
    
    
        LoginManager.checkLoginStatus { isLogged in
    
            if isLogged {
    
                // Updates your UIs on main queue
                DispatchQueue.main.async(execute: {
    
                if self.priceTextField.text == "" {
                    GlobalVariables.sharedManager.itemPrice = 0
                } else {
                    GlobalVariables.sharedManager.itemPrice = Double(self.priceTextField.text!)!
                }
    
                if self.titleTextView.text == "" {
                    GlobalVariables.sharedManager.expenseTitle = "N/A"
                } else {
                    GlobalVariables.sharedManager.expenseTitle = self.titleTextView.text!
                }
    
                if self.descriptionTextView.text == "" {
                    GlobalVariables.sharedManager.expenseDescription = "N/A"
                } else {
                    GlobalVariables.sharedManager.expenseDescription = self.descriptionTextView.text!
                }
    
                if self.categoryPickerTextFld.text == "" {
                    GlobalVariables.sharedManager.expenseCategory = "N/A"
                } else {
                    GlobalVariables.sharedManager.expenseCategory = self.categoryPickerTextFld.text!
                }
    
    
                if self.imageView.image == nil {
                    GlobalVariables.sharedManager.expenseSelectedImage = nil
                } else {
                    GlobalVariables.sharedManager.expenseSelectedImage = self.imageView.image
                }
    
    
                }) 
    
            }
        }
    }
    



    或者,您可以通过从项目目标禁用主线程检查器来禁用警告

    (Xcode 项目目标 - 在设备列表下方)>> 编辑方案 >> 目标 >> 诊断 >> 运行时 API 检查 - 取消选中

    【讨论】:

    • 借助OCR工具
    【解决方案3】:

    登录管理器正在主线程以外的线程上运行您的闭包,您不能在主线程之外使用用户界面元素。

    其他人说只读取侧线程上的 UI 属性就可以了,他们可能是对的,但没有绝对的保证,而且就个人而言,我会注意警告。例如,访问这些属性可能会产生副作用。也许它们的值被缓存在某个地方,而主线程正在更新或删除该属性时,就在您想要访问它时。

    消除警告的正确方法是在主线程上执行你的闭包,例如

    LoginManager.checkLoginStatus {
        isLoggedIn in
    
        DispatchQueue.main.async {
    
            // Do all your UI stuff here
    
        }
     }
    

    这样,运行闭包的线程除了将代码安排在始终在主线程上运行的主队列中运行之外,什么都不做。

    【讨论】:

      【解决方案4】:

      警告似乎过于激进,因为您暗示您只是检查 textField 是否为空,而不是更改 UI 上的任何内容。该警告试图阻止在主线程之外使用任何 UI 元素,这当然不是一件坏事,但它没有考虑到像你这样的边缘情况。

      【讨论】:

        【解决方案5】:

        问题正是如此 - 您正在使用后台线程中的 UI 元素。尝试修改您的代码以便从主线程访问它们。

        Xcode 9 有新功能 - 它可以在运行时检查此类问题并在执行期间报告。

        如果您真的不想要它,您可以在方案设置中禁用它。编辑方案... ->(选择您的方案)-> 诊断 -> 禁用“主线程检查器”

        【讨论】:

        • 感谢您的回复。我认为解决问题而不是仅仅禁用警告是有意义的。你能推荐一个解决方案吗?我不确定如何将 IF 语句汇集到主队列中......
        • DispatchQueue.main.async { if self.priceTextField.text == "" { GlobalVariables.sharedManager.itemPrice = 0 }else{ GlobalVariables.sharedManager.itemPrice = Double(self.priceTextField.text!) ! } } 我认为这行不通....
        • 您尝试过DispatchQueue.main.async 吗?我认为它会起作用并且非常有意义 - 你在后台线程(在你的情况下登录)上做了一些冗长的事情,然后你回到主线程以更新 UI。
        【解决方案6】:

        XCode 9 包含一个Main thread checker 工具,用于检查主线程上是否发生了任何与 UIKit 相关的事情。它应该防止从后台线程触摸 UIKit 会产生问题的情况。

        虽然建议保留此工具,但如果它对您来说太麻烦,您可以将其关闭:

        XCode->Edit Scheme->Target->Diagnostics->取消选中RunTime API Checking

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-07-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多