问题
Not sure why after updating to Xcode 9 my project (originally created in Swift 3) is showing purple warnings: UITextField.text must be used from main thread only
I'm only checking in If statement if text field is empty... attaching screenshot.
回答1:
The login manager is running your closure on a thread other than the main thread and you can't use user interface elements off the main thread.
Others have said that it's OK just to read UI properties on side threads and they are probably right, but there is no absolute guarantee of it and, personally, I would heed the warnings. For example, accessing those properties could have side effects. Perhaps their values are cached somewhere and the main thread is in the process of updating or deleting the property just when you want to access it.
The proper way to silence the warnings is to execute your cloasure on the main thread e.g.
LoginManager.checkLoginStatus {
isLoggedIn in
DispatchQueue.main.async {
// Do all your UI stuff here
}
}
This way the thread that runs the closure does nothing except schedules the code to run in the main queue which always runs on the main thread.
回答2:
Simply adding DispatchQueue.main.async will prevent this and is recommended in the swift documentation.
DispatchQueue.main.async {
//code that caused error goes here
}
回答3:
XCode 9 includes a Main thread checker tool that checks whether any UIKit related stuff is happening on a main thread. It is supposed to prevent the cases where touching UIKit from a background thread, is going to create problems.
Although, it is advisable to keep this tool around, but if its too much a bother for you, you can turn it off:
XCode->Edit Scheme->Target->Diagnostics-> Uncheck RunTime API Checking
回答4:
The problem exactly that it is - you are using UI elements from background thread. Try to modify your code in order to access them from main thread.
Xcode 9 have new feature - it can check problems like this on runtime and report it during execution.
If you REALLY do not want it, you can disable it in scheme settings. Edit Scheme... -> (Select your scheme) -> Diagnostics -> Disable 'Main thread checker'
回答5:
Here is Apple Guideline on Main Thread Checker
- New in Xcode 9 – Main Thread Checker.
- Enable detection of UI API misuse from background thread
- Detects AppKit, UIKit, and WebKit method calls that are not made on the main thread.
- Automatically enabled during debugging, and can be disabled in the Diagnostic tab of the scheme editor.
- Main Thread Checker works with Swift and C languages.
Try this: Replace your code with following one, and see. It's a permanent solution, without disabling warning.
@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
}
})
}
}
}
or, you can just disable warning, by disabling main thread checker from your project target
(Xcode Project Target - Below Device List) >> Edit Scheme >> Target >> Diagnostics >> RunTime API Checking - Uncheck
回答6:
The warnings seem overly aggressive as you imply by stating that you are only checking if a textField is empty, not changing anything on the UI. The warning is trying to discourage any use of UI elements off of the main thread, which is not a bad thing of course, but it doesn't take into account edge cases like yours.
来源:https://stackoverflow.com/questions/46490140/xcode-9-update-swift-purple-warning