简体   繁体   中英

iOS Swift Only run on the main thread error for app

I am new to swift and I have a login page that takes the users credentials and check if it's the right credentials . I think return the response in JSON if it's the right credentials then I try to go to a new ViewController .I got this error when I try to go to a new View Controller, I have this in a closure so I do not know why I am getting this issue. This is my code

func LoginClosure(completion:@escaping (Bool) ->Void) {
    var check = 0
    let url:URL = URL(string:ConnectionString+"login")!

    if submitEmail == nil || submitPassword == nil {
        submitEmail = email.text!
        submitPassword = password.text!
    }

    let session = URLSession.shared
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    let parameter = "Email=\(submitEmail!)&password=\(submitPassword!)"
    request.httpBody = parameter.data(using: String.Encoding.utf8)
    DispatchQueue.main.async {
        session.dataTask(with:request, completionHandler: { (data, response, error) in
            if error != nil {
                // print(error)
            } else {
                do {
                    let parsedData = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:Any]

                    if let Streams = parsedData?["Profile"] as? [AnyObject]  {
                        // check for misspelled words
                        for Stream in Streams {
                            if let rr = Stream["result"] as? Bool {
                                self.result = rr
                            } else {
                                self.result = true
                            }

                            if let id = Stream["id"] as? Int {
                                self.defaults.setValue(id, forKey: "my_id")
                                // Success
                                MYID = id
                                completion(true)
                                return
                            }
                        }

                        if check == 0 {
                            // Bad credentials
                            completion(false)
                        }
                    }
                } catch let error as NSError {
                    print(error)
                }
            }
        }).resume()
    }
}

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Only run on the main thread!'

That error occurs with this line:

let next = self.storyboard?.instantiateViewController(withIdentifier: "AccountC") as! AccountC
self.present(next, animated: true, completion: nil)

As per apple standards, you have to perform UI activity in the main queue only.

Just call your closure in the main queue as below.

DispatchQueue.main.async {
    completion(true)
}

You can also perform only UI changes in the main queue as below.

DispatchQueue.main.async {
    let next = self.storyboard?.instantiateViewController(withIdentifier: "AccountC") as! AccountC
    self.present(next, animated: true, completion: nil)
}

@rmaddy Thanks for the valuable suggestion.

In your code, I see that you have initiated the network call in the main queue. That makes sure that creation of the data task and starting it off will be performed on the main thread. But it doesn't guarantee that the completion closure will also be called on the main thread.

Therefore I would suggest removing the network call from the DispatchQueue.main.async block. Then please execute the code that performs UI updation in a DispatchQueue.main.async block as follows.

DispatchQueue.main.async {    
    let next = self.storyboard?.instantiateViewController(withIdentifier: "AccountC") as! AccountC
    self.present(next, animated: true, completion: nil)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM