2017-04-12 1 views
0

J'ai créé un script pour la connexion dans mon application. L'utilisateur tape son nom d'utilisateur et son mot de passe, puis j'envoie ces valeurs au serveur. J'ai un script php pour vérifier les valeurs de la base de données, puis je renvoie un tableau codé json à mon application. J'analyse le résultat, stocke les valeurs dans userdefaults, puis continue dans l'application. Tout allait bien jusqu'à ce que j'ai implémenté une autre fonctionnalité pour renvoyer un devis d'une base de données.Erreur Domaine = NSCocoaErrorDomain Code = 3840 "Aucune valeur".

L'erreur est extrêmement particulière parce que il n'arrive pas à chaque fois, mais assez fréquemment cela pose problème. Je ne comprends pas pourquoi


Swift:

let myUrl = NSURL(string: "https://www.example.com/scripts/userLogin.php"); 
    let request = NSMutableURLRequest(url:myUrl! as URL) 

    request.httpMethod = "POST"; 
    let postString = "username=\(username)&password=\(password)"; 
    request.httpBody = postString.data(using: String.Encoding.utf8); 

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

     if error != nil { 
      print("error=\(String(describing: error))") 
      return 
     } 

     // Parse the results of the JSON result and naivigate to app if success 
     var err: NSError? 
     do { 
      let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary 
      if let parseJSON = json { 

       let resultValue:String = parseJSON["status"] as! String; 

        if (resultValue == "Success"){ 

        let storedUserID: String = parseJSON["user_id"] as! String; 
        let storedUsername: String = parseJSON["username"] as! String; 
        let storedFirstname: String = parseJSON["firstname"] as! String; 
        let storedSurname: String = parseJSON["surname"] as! String; 
        let storedUniName: String = parseJSON["uni_name"] as! String; 
        let storedUniCourse: String = parseJSON["uni_course"] as! String; 
        let storedEmail: String = parseJSON["email"] as! String; 
        let storedVerificationCode: String = parseJSON["verification_code"] as! String; 
        let theQuote: String = parseJSON["quote"] as! String 

        let array = [storedUserID, storedUsername, storedFirstname, storedSurname, storedUniName, storedUniCourse, storedEmail, storedVerificationCode, theQuote] 

        UserDefaults.standard.set(array, forKey: "UserDetailsArray"); 
        UserDefaults.standard.set(true, forKey: "isUserLoggedIn"); 
        UserDefaults.standard.synchronize(); 

        print("Successfully logged in with:") 
        print(array) 

        DispatchQueue.main.async{ 
         let mainTabBar = self.storyboard?.instantiateViewController(withIdentifier: "mainTabBar") as! UITabBarController; 
         let appDelegate = UIApplication.shared.delegate as! AppDelegate; 
         appDelegate.window?.rootViewController = mainTabBar 
        } 
       } 
      } 
     } catch let error as NSError { 
      err = error 
      print(err!); 
     } 
    } 
    task.resume(); 

PHP:

$check = query_mysql("SELECT * FROM users WHERE username='".$username."'"); 

if ($check->num_rows == 0) { 
    $returnValue["status"] = "Error"; 
    $returnValue["message"] = "No such details found on server"; 
    echo json_encode($returnValue); 
} else { 
    while ($row = $check->fetch_assoc()){ 
     $storedUserID  = $row['user_id']; 
     $storedUsername  = $row['username']; 
     $storedfirstname = $row['firstname']; 
     $storedsurname  = $row['surname']; 
     $storedPass   = $row['password']; 
     $storedUniName  = $row['uni_name']; 
     $storedUniCourse = $row['uni_course']; 
     $storedEmail  = $row['email']; 
     $storedVerificationCode = $row['unique_code']; 
     $verified   = $row['verified']; 
    } 

    if ($storedPass != $password) { 
     $returnValue["status"] = "Failed"; 
     $returnValue["message"] = "The user and password combination do not match"; 
     echo json_encode($returnValue); 

    } elseif ($verified == 0){ 
     $returnValue["status"] = "Unverified"; 
     $returnValue["message"] = "The email associated with this account has not been verified"; 
     echo json_encode($returnValue); 

    } else { 

     // Retrieve a motivational quote 
     $get_quote = query_mysql("SELECT quote FROM study_quotes ORDER BY rand() LIMIT 1"); 

     if (!$get_quote){ 
      $returnValue["quote"] = "Failed"; 
     } else { 
      while ($row = $get_quote->fetch_assoc()) $returnValue["quote"] = $row['quote']; 
     } 

     $returnValue["status"]    = "Success"; 
     $returnValue["user_id"]    = $storedUserID; 
     $returnValue["username"]   = $storedUsername; 
     $returnValue["firstname"]   = $storedfirstname; 
     $returnValue["surname"]    = $storedsurname; 
     $returnValue["uni_name"]   = $storedUniName; 
     $returnValue["uni_course"]   = $storedUniCourse; 
     $returnValue["email"]    = $storedEmail; 
     $returnValue["verification_code"] = $storedVerificationCode; 
     echo json_encode($returnValue); 

Base de données:

A une table avec id et quote (pré-rempli avec mes propres données auxquelles l'utilisateur n'a pas accès. Je sais qu'il y aura toujours des lignes actuelles, je ne vérifie si num_rows mais seulement si la requête échoue)


Utilisation:

J'utilise UserDefaults parce que sur l'écran suivant, j'utiliser le 8ème indice (qui est la citation) pour définir une étiquette:

let userDetails: [String] = UserDefaults.standard.stringArray(forKey:"UserDetailsArray")! 
self.quoteLabel.text = userDetails[8] 

Il me semble avoir un succès de 50% et 50% taux d'échec. Je recevrai l'erreur:

Error Domain=NSCocoaErrorDomain Code=3840 "No value." UserInfo={NSDebugDescription=No value.} 
+0

Quelle ligne de code est à l'origine de l'erreur? – rmaddy

+0

L'instruction catch du script swift en bas où l'erreur est imprimée: 'catch let error as NSError { err = erreur print (err!); } ' – Nouman

+0

On dirait que vous obtenez mauvais JSON. Quand vous obtenez une erreur, convertissez 'data' en' String' en utilisant: 'String (données: données!, Encodage: .utf8)' et voyez le résultat. – rmaddy

Répondre

0

Merci à rmaddy pour aider. J'ai trouvé un hack qui semble fonctionner pour relancer la fonction à chaque fois jusqu'à ce que l'ensemble de données retourné ne soit pas vide, mais je suis sûr que ce n'est pas la bonne chose à faire même si cela fonctionne.

  } catch let error as NSError { 
      let dataSet = String(data: data!, encoding: .utf8) 

      print("Trying again") 
      if (dataSet?.isEmpty)!{ 
       self.LoginButtonTapped(self) 
      } 

      err = error 
      print(err!); 
     }