waitUntilAllTasksAreFinished error Swift

17,321

Solution 1

Your checkLogin function is being called on another thread, so you need to switch back to the main thread before you can call self.performSegueWithIdentifier. I prefer to use NSOperationQueue:

func checkLogin(succeed: Bool, msg: String) {
    if (succeed) {
        NSOperationQueue.mainQueue().addOperationWithBlock {
            self.performSegueWithIdentifier("logInTrue", sender: self)
        }        
    }
}

Alternate: xCode 10.1 1/2019

func checkLogin(succeed: Bool, msg: String) {
    if (succeed) {
        OperationQueue.main.addOperation {
            self.performSegue(withIdentifier: "logInTrue", sender: self)
           }        
      }
 }

Solution 2

With Xcode 8.0 and Swift 3, this has been modified to the following construct:

OperationQueue.main.addOperation{
    <your segue or function call>
}

Solution 3

I was also having same issue, got resolved by taking reference from above answer. Thank you @Nate

var storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
var vc: UINavigationController = storyBoard.instantiateViewControllerWithIdentifier("AppViewController") as! UINavigationController

NSOperationQueue.mainQueue().addOperationWithBlock {
    self.presentViewController(vc, animated: true, completion: nil)
}
Share:
17,321
Liran Revivo
Author by

Liran Revivo

Updated on June 27, 2022

Comments

  • Liran Revivo
    Liran Revivo almost 2 years

    I have this call in my loginViewController when Submit button is pressed:

    let http = HTTPHelper()
        http.post("http://someUrl.com/Login/userEmail/\(username.text)/Pswd/\(userPass.text)", postCompleted: self.checkLogin)
    

    while the checkLogin function I send is only performing:

    func checkLogin(succeed: Bool, msg: String){
        if (succeed){
            self.performSegueWithIdentifier("logInTrue", sender: self)
        }
    }
    

    the post function is HTTPHelper class is :

    func post(url : String, postCompleted : (succeeded: Bool, msg: String) -> ()) {
        var request = NSMutableURLRequest(URL: NSURL(string: url)!)
        var session = NSURLSession.sharedSession()
        request.HTTPMethod = "POST"
        var err: NSError?
         self.task = session.dataTaskWithURL(NSURL(string: url)!)  {(data, response, error) in
            var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
            var err: NSError?
            var json = NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments, error: &err) as? NSDictionary
            var msg = "No message"
            // Did the JSONObjectWithData constructor return an error? If so, log the error to the console
            if(err != nil) {
                let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
                postCompleted(succeeded: false, msg: "Error")
            }
            else {
                // The JSONObjectWithData constructor didn't return an error. But, we should still
                // check and make sure that json has a value using optional binding.
                if let parseJSON = json {
                    // Okay, the parsedJSON is here, let's get the value for 'success' out of it
                    if let success = parseJSON["result"] as? Bool {
                        postCompleted(succeeded: success, msg: "Logged in.")
                    }
                    return
                }
                else {
                    // Woa, okay the json object was nil, something went worng. Maybe the server isn't running?
                    let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
                    postCompleted(succeeded: false, msg: "Error")
                }
            }
        }
    
        self.task!.resume()
    }
    

    when the checkLogin function is called with success: true it fails to performSegueWithIdentified function .. the error looks like:

    Assertion failure in -[UIKeyboardTaskQueue waitUntilAllTasksAreFinished], /SourceCache/UIKit_Sim/UIKit-3318.16.14/Keyboard/UIKeyboardTaskQueue.m:374 2014-11-15 17:41:29.540 Wavesss[8462:846477] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[UIKeyboardTaskQueue waitUntilAllTasksAreFinished] may only be called from the main thread.'

    please help me though I am struggling very hard to find a solution for this, it seems like I can't pass between view controllers while the url task is still being performed on other thread. thanks in advance guys!