答案 0 :(得分:9)
登录管理器在主线程以外的线程上运行闭包,你不能在主线程上使用用户界面元素。
其他人已经说过只读边线上的UI属性就可以了,但它们可能是对的,但是没有绝对的保证,而且个人而言,我会注意这些警告。例如,访问这些属性可能会产生副作用。也许他们的值被缓存在某个地方,主要线程正在更新或删除属性的过程中,只是当你想要访问它时。
使警告静音的正确方法是在主线程上执行你的礼物,例如
LoginManager.checkLoginStatus {
isLoggedIn in
DispatchQueue.main.async {
// Do all your UI stuff here
}
}
这样运行闭包的线程除了调度代码在主队列中运行总是在主线程上运行之外什么都不做。
答案 1 :(得分:5)
XCode 9包含一个Main thread checker工具,用于检查主线程上是否发生了任何与UIKit相关的事情。它应该可以防止从后台线程触摸UIKit的情况会产生问题。
虽然,建议保留此工具,但如果对您来说太麻烦,可以将其关闭:
XCode->编辑方案 - >目标 - >诊断 - >取消选中RunTime API检查
答案 2 :(得分:3)
简单地添加DispatchQueue.main.async会阻止这种情况,建议在swift文档中使用。
DispatchQueue.main.async {
//code that caused error goes here
}
答案 3 :(得分:1)
确切地说问题是 - 您正在使用后台线程中的UI元素。尝试修改代码,以便从主线程访问它们。
Xcode 9具有新功能 - 它可以在运行时检查这样的问题并在执行期间报告它。
如果您真的不想要它,可以在方案设置中禁用它。编辑方案... - > (选择你的方案) - >诊断 - >禁用“主线程检查器”
答案 4 :(得分:1)
以下是主线程检查器上的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检查 - 取消选中
答案 5 :(得分:-1)
警告似乎过于激进,因为您暗示您只是检查textField是否为空,而不是更改UI上的任何内容。该警告试图阻止从主线程中使用UI元素,这当然不是坏事,但它没有考虑像你这样的边缘情况。