web-dev-qa-db-fra.com

waitUntilAllTasksAreFinished error Swift

J'ai cet appel dans mon loginViewController lorsque le bouton Soumettre est enfoncé:

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

tandis que la fonction checkLogin que j'envoie n'effectue que:

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

la fonction post est la classe HTTPHelper est:

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

lorsque la fonction checkLogin est appelée avec succès: true, elle ne parvient pas à exécuter la fonctionSegueWithIdentified .. l'erreur ressemble à:

Échec de l'assertion dans - [UIKeyboardTaskQueue waitUntilAllTasksAreFinished], /SourceCache/UIKit_Sim/UIKit-3318.16.14/Keyboard/UIKeyboardTaskQueue.m:374 2014-11-15 17: 41: 29.540 Wavesss [8462: 846477] *** Terminaison de l'application exception non interceptée 'NSInternalInconsistencyException', raison: '- [UIKeyboardTaskQueue waitUntilAllTasksAreFinished] ne peut être appelé qu'à partir du thread principal.'

s'il vous plaît, aidez-moi bien que je lutte très dur pour trouver une solution à cela, il semble que je ne puisse pas passer entre les contrôleurs de vue pendant que la tâche url est toujours en cours d'exécution sur un autre thread. merci d'avance les gars!

34
Liran Revivo

Votre fonction checkLogin est appelée sur un autre thread, vous devez donc revenir au thread principal avant de pouvoir appeler self.performSegueWithIdentifier. Je préfère utiliser NSOperationQueue:

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

Autre: xCode 10.1 1/2019

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

Avec Xcode 8.0 et Swift 3, cela a été modifié pour la construction suivante:

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

J'avais également le même problème, résolu en prenant la référence de la réponse ci-dessus. Merci @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)
}
2