错误域=NSCocoaErrorDomain 代码=3840 "No value."

Error Domain=NSCocoaErrorDomain Code=3840 "No value."

我已经在我的应用程序中创建了一个用于登录的脚本。用户输入他们的用户名和密码,然后我将这些值发送到服务器。我有一个 php 脚本来检查数据库值,然后我 return 一个 json 编码数组返回我的应用程序。我解析结果,将值存储在 userdefaults 中,然后进入应用程序。一切都很好,直到我实现了另一个功能 return 来自数据库的报价。

该错误非常特殊,因为它不会每次都发生,但它发生的频率足以引起问题。我不明白为什么


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

数据库:

有一个带有 id 和引号的 table(预填充了我自己的用户无权访问的数据。我知道总会有行存在,所以我从不检查 num_rows,但前提是查询失败)


用法:

我使用 UserDefaults 是因为在下一个屏幕上,我使用第 8 个索引(即引号)设置为标签:

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

我好像有 50% 的成功率和 50% 的失败率。我会收到错误:

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

感谢 rmaddy 的帮助。我发现了一个 hack,它似乎每次都可以基本上重新 运行 函数,直到返回的数据集不为空,但我很确定这不是正确的做法,即使它有效,所以任何帮助都会仍然受到赞赏:

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