2017-08-29 5 views
-1

J'essaye de créer un formulaire de réenregistrement d'utilisateur, qui devrait vérifier si l'utilisateur existe déjà. Donc, j'envoie une requête php à mon serveur mysql. Si la valeur de retour est vide, l'utilisateur n'existe pas encore.Comment attendre qu'une tâche de téléchargement se termine dans swift 3

Malheureusement, je suis vraiment bloqué par l'attente de la fin de cette vérification. J'ai essayé plusieurs solutions que j'ai trouvées googleing mais aucun d'eux n'a fonctionné. Mon code actuel utilise des sémaphores et va planter avec "erreur fatale: trouvé de manière inattendue nil lors du déballage d'une valeur optionnelle", donc le sémaphore n'attend pas que la tâche soit finie comme je l'attendrais.

Tous les conseils, seraient grandement appréciés. Merci les gars.

private func isUniqueEmail(email: String) -> Bool { 
    var result: Bool? 
    let semaphore = DispatchSemaphore(value: 1) 
    let requestURL = URL(string: "http://localhost/firstpostget/functions/get.php") 
    var request = URLRequest(url: requestURL!) 
    request.httpMethod = "POST" 
    let postParameters = "email=" + email 
    request.httpBody = postParameters.data(using: .utf8) 
    let configuration = URLSessionConfiguration.default 
    let session = URLSession(configuration: configuration, delegate: nil, delegateQueue: OperationQueue.main) 
    let task = session.dataTask(with: request) {(data, response, error) in 
     var myJson: AnyObject 
     do{ 
      myJson = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject 
      if myJson.count == 0{ 
       result = true 
       semaphore.signal() 
      } else{ 
       result = false 
       semaphore.signal() 
      } 
     } catch{ 
      //TODO 
      print(error) 
     } 
    } 
    task.resume() 

    semaphore.wait(timeout: .distantFuture) 
    return result! 
} 
+1

NE PAS "ATTENDRE". N'UTILISEZ PAS DE SEMAPHORE. – matt

Répondre

1

Votre tâche est async et vous êtes force de dépliage valeur nulle si c'est la raison pour laquelle il se bloque.

Vous devez changer votre implémentation de la fonction d'être aussi async, par exemple en utilisant des fermetures:

private func isUniqueEmail(email: String, completion: ((Bool) -> (Void))?) { 
    let requestURL = URL(string: "http://localhost/firstpostget/functions/get.php") 
    var request = URLRequest(url: requestURL!) 
    request.httpMethod = "POST" 
    let postParameters = "email=" + email 
    request.httpBody = postParameters.data(using: .utf8) 
    let configuration = URLSessionConfiguration.default 
    let session = URLSession(configuration: configuration, delegate: nil, delegateQueue: OperationQueue.main) 
    let task = session.dataTask(with: request) {(data, response, error) in 
     var myJson: AnyObject 
     do{ 
      myJson = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject 
      if myJson.count == 0 { 
       completion?(true) 
      } else{ 
       completion?(false) 
      } 
     } catch{ 
      //TODO 
      print(error) 
     } 
    } 
    task.resume() 
} 

Maintenant, vous pouvez utiliser cette fonction ainsi:

isUniqueEmail(email: "[email protected]") { result in 
    if result { 
     print("email unique") 
    } else { 
     print("email not unique") 
    } 
} 
+0

Merci beaucoup! Cela fonctionne très bien.:) –

+0

Désolé, en fait, j'ai besoin d'utiliser le Bool pour valider le résultat et non seulement l'imprimer sur la console. Et je ne peux pas faire ça avec ta solution. –

+0

Bien sûr que vous pouvez. Vous avez votre bool dans la variable de résultat –

1

Je pense que vous devriez repenser le modèle que vous utilisez pour extraire les données de votre requête, vous devez envisager d'utiliser une méthode de gestionnaire/rappel personnalisée que vous transmettez avec l'e-mail que vous essayez de vérifier. Voir ci-dessous un exemple:

private func isUniqueEmail(email: String, handler: ((_ result: Bool) -> Void)?) -> Void { 
    let requestURL = URL(string: "http://localhost/firstpostget/functions/get.php") 
    var request = URLRequest(url: requestURL!) 
    request.httpMethod = "POST" 
    let postParameters = "email=" + email 
    request.httpBody = postParameters.data(using: .utf8) 
    let configuration = URLSessionConfiguration.default 
    let session = URLSession(configuration: configuration, delegate: nil, delegateQueue: OperationQueue.main) 
    let task = session.dataTask(with: request) {(data, response, error) in 
     var myJson: AnyObject 
     var result: Bool = false 
     do{ 
      myJson = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject 

      if myJson.count == 0 { 
       result = true 
      } 

      guard handler != nil else { 
       return 
      } 

      handler!(result) 

     } catch{ 
      //TODO 
      print(error) 
     } 
    } 
    task.resume() 
} 

Run:

isUniqueEmail(email: "[email protected]", handler: { result in 
    print(result) // true || false 
}) 

Si vous voulez vraiment aller sur le "attendre" la route puis prendre Touque à DispatchGroup « s

https://developer.apple.com/documentation/dispatch/dispatchgroup

0

vous pouvez utiliser URlSession comme:

 func isUniqueEmail(email: String,completion: @escaping (Bool) ->()) { 

    var request = URLRequest(url: URL(string: "http://localhost/firstpostget/functions/get.php")!) 
    request.httpMethod = "POST" 
    let postString = "email=\(email)" 
    request.httpBody = postString.data(using: .utf8) 


    // loading to wait request 
    UIApplication.shared.isNetworkActivityIndicatorVisible = true 


    let task = URLSession.shared.dataTask(with: request) { data, response, error in 

     // we get request request 

     UIApplication.shared.isNetworkActivityIndicatorVisible = false 

     guard let data = data, error == nil else {             // check for fundamental networking error 
      print("error=\(String(describing: error))") 
      completion(false) 

      return 
     } 

     if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {   // check for http errors 
      print("statusCode should be 200, but is \(httpStatus.statusCode)") 
      print("response = \(String(describing: response))") 
      completion(false) 
     }else{ 

      completion(true) 

     } 


     let responseString = String(data: data, encoding: .utf8) 
     print("responseString = \(String(describing: responseString))") 
    } 



    task.resume() 
} 

et utilisé dans le code comme

self.isUniqueEmail(email: "your Email") { (isExit) in 

    if isExit { 


    }else{ 


    } 
} 
+0

Désolé, je n'ai pas vraiment votre réponse. Je ne peux plus voir la vérification s'il y a une réponse à la requête et peu importe ce que je tape dans le fichier if isExit est toujours exécuté. –

+0

Vous appelerez cette méthode s'il y a réponse isExit est vrai sinon ce sera faux –

+0

Il ne fonctionne pas alors. Peu importe s'il y a une réponse ou non isExit est toujours vrai. –

0

essayer d'utiliser ceci:

ApihelperClass

static let sharedInstance = ApihelperClass() 

typealias CompletionHandler = (_ success:Bool, _ error:Bool, _ result:NSDictionary) -> Void 
typealias ErrorHandler = (_ success: Bool, _ error:Bool) -> Void 

    func callPostRequest(_ urlPath: String, params:[String: AnyObject], completionHandler: @escaping CompletionHandler, errorHandler:@escaping ErrorHandler){ 

     print("urlPath:==> \(urlPath) ") 
     let session = Foundation.URLSession.shared 
     let url = URL(string: urlPath) 
     var request = URLRequest(url : url!) 
     request.httpMethod = "POST" 

     do { 

      let jsonData = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted) 

      request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type") 
      request.httpBody = jsonData 

      session.dataTask(with: request, completionHandler: { data, response, error in 
       OperationQueue.main.addOperation { 

        guard error == nil && data != nil else {               // check for fundamental networking error 
         print("error=\(error)") 
         errorHandler(false, true) 
         return 
        } 

        if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {   // check for http errors 
         print("statusCode should be 200, but is \(httpStatus.statusCode)") 
         //       print("response = \(response)") 
        } 

        let responseString = String(data: data!, encoding: String.Encoding.utf8) 
        print("responseString = \(responseString!)") 

        if let responsedata = responseString!.data(using: String.Encoding.utf8)! as? Data{ 

         do { 

          let jsonResult:NSDictionary = try JSONSerialization.jsonObject(with: responsedata, options: []) as! NSDictionary 
          print("Get The Result \(jsonResult)") 
//parse your jsonResult as per your requirements 
          if error != nil { 
           print("error=\(error)") 

           completionHandler(false, true, jsonResult)// 
          } 


          if let str = jsonResult["success"] as? NSNull { 
           print("error=\(str)") 

           completionHandler(false, true, jsonResult) 

          } 
          else { 
           let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue) 
           //         print("Response string : \(responseString)") 
           completionHandler(true, false, jsonResult) 
          } 



         } catch let error as NSError { 
          print(error.localizedDescription) 
         } 
        } 
       } 
      }) .resume() 
     }catch { 
       print("Error ->Catch") 
     } 
    } 

Ajouter à votre viewcontroller

func isUniqueEmail(email: String){ 
    ApihelperClass.sharedInstance.callPostRequest("http://localhost/firstpostget/functions/get.php", params: ["email":email as AnyObject], completionHandler: { (success, error, result) in 
     //success 200 
    }) { (success, error) in 
     //error 
    } 
} 
+0

Merci beaucoup pour votre réponse. Où pourrais-je mettre la classe Apihelper? –

+0

Créez Apihelper.swift et collez-y le code – Yuyutsu

0

Ok, je viens de trouver une solution. Mon approche de sémaphore a fonctionné aussi bien que dispatchgroups. La tâche devait juste être URLSession.shared.dataTask

Encore merci beaucoup pour toutes les réponses.