Search code examples
iosswiftuistoryboard

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)

Solution

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