Liran Revivo Liran Revivo - 5 months ago 11
iOS Question

waitUntilAllTasksAreFinished error Swift

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!

Answer

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