Xcode 9 update Swift, purple warning

12,736

Solution 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.

Solution 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
}

Solution 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

enter image description here

Solution 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'

Solution 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

enter image description here

Share:
12,736
KirillC
Author by

KirillC

Updated on June 07, 2022

Comments

  • KirillC
    KirillC almost 2 years

    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.

    enter image description here

  • KirillC
    KirillC over 6 years
    Thanks for your response. I think it makes sense to address the problem rather than just disable warnings. Can you recommend a solution ? I'm not sure how to funnel the IF statement into the Main Queue...
  • KirillC
    KirillC over 6 years
    DispatchQueue.main.async { if self.priceTextField.text == "" { GlobalVariables.sharedManager.itemPrice = 0 }else{ GlobalVariables.sharedManager.itemPrice = Double(self.priceTextField.text!)! } } I don't think this would work....
  • Anton  Malmygin
    Anton Malmygin over 6 years
    Did you tried already with DispatchQueue.main.async ? I think it will work and make perfect sense - you do something lengthy on background thread (login in your case) and after you came back to main thread in order to update UI.
  • Krunal
    Krunal over 6 years
    with the help of OCR tool