Ios 为什么解析JSON时会出现错误代码=3840?

Ios 为什么解析JSON时会出现错误代码=3840?,ios,json,swift,api,strongloop,Ios,Json,Swift,Api,Strongloop,一般来说,我对Swift和iOS开发还不熟悉。我正在测试和学习如何使用远程服务器api。我在尝试身份验证时从一个Strongloop(Loopback)api获取JSON,我尝试使用的解析得到一个错误: Error Domain=NSCOCAERRORDOMAIN Code=3840“该操作无法完成。(可可错误3840)。“(无值。)UserInfo=0x7fd623e38870{NSDebugDescription=无值。} 这是字符串中的返回值,我显然从环回中得到了正确的JSON响应、身份验

一般来说,我对Swift和iOS开发还不熟悉。我正在测试和学习如何使用远程服务器api。我在尝试身份验证时从一个Strongloop(Loopback)api获取JSON,我尝试使用的解析得到一个错误:

Error Domain=NSCOCAERRORDOMAIN Code=3840“该操作无法完成。(可可错误3840)。“(无值。)UserInfo=0x7fd623e38870{NSDebugDescription=无值。}

这是字符串中的返回值,我显然从环回中得到了正确的JSON响应、身份验证令牌、ttl、日期和用户ID:

{“id”:“BHZKNJRBUPN9KSC1GEGQTNHJFNWUIFNxpFZUKYXC5IWRDEHUERURRVSDBMZZRVI”,“ttl”:1209600,“创建”:“2015-07-03T13:04:39.791Z”,“用户id”:2}

我认为实际问题不是发生在parseJSON方法中,而是发生在performLoginRequestWithURL方法中。它正在返回一个空字符串。这与异步请求有关。我注意到json字符串变量直到从方法返回后才被设置,因此返回为空。如果我放置两个println(json)方法,一个在异步请求内部,一个在异步请求之后,一个在异步请求之后,第一个在println之后。这在某种程度上是有道理的,但我不知道如何解决这个问题。我需要从帖子中返回json,但我不知道如何捕获它。有些东西告诉我我需要使用同步请求,但我不知道在从POST请求获取json的上下文中如何做到这一点

这是我的密码:

//Login button pressed
@IBAction func login() {
    //Gets url string
    let url = getLogin()
    //Posts url with UITextField data.
    if let jsonString = performLoginRequestWithURL(url) {
        //Error occurs in the parseJSON method
        if let dictionary = parseJSON(jsonString) {
            /*
            if let at = dictionary["id"] as? String {
                accesstoken = at
            }
            if let id = dictionary["userId"] as? Int {
                println(id)
            }
            */
        }
    }

}

func getLogin() -> NSURL {
    let toEscape = "http://localhost:3000/api/Users/login"
    let urlString = toEscape.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!
    let url = NSURL(string: urlString)
    return url!
}

func performLoginRequestWithURL(url: NSURL) -> String? {
    let bodyData = "username=\(textEmail.text)&password=\(textPW.text)"
    var request: NSMutableURLRequest = NSMutableURLRequest(URL: url)
    var json = ""
    request.HTTPMethod = "POST"
    request.HTTPBody = bodyData.dataUsingEncoding(NSUTF8StringEncoding)
    NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()){
        response, data, error in

        if data != nil {
            json = NSString(data: data, encoding: NSUTF8StringEncoding) as! String
        }
        println(json)
    }
    return json
}

func parseJSON(jsonString: String) -> [String: AnyObject]? {
    if let data = jsonString.dataUsingEncoding(NSUTF8StringEncoding) {
        var error: NSError?
        if let json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(0), error: &error) as? [String: AnyObject] {
            return json
        } else if let error = error {
            //Here's where the error comes back.
            println("JSON Error: \(error)")
        } else {
            println("Unknown JSON Error")
        }
    }
    return nil
}

我用问题中的字符串测试了
parseJSON
,结果成功,因此错误一定是字符串没有正确发送到
parseJSON
方法

let jsonString = "{\"id\":\"BHzKnjrbUPn9KSC1GegQTNHJFNwfuifNXPfZuKkYxC5IwRDEHuerurvSdBMzzrVi\",\"ttl\":1209600,\"created\":\"2015-07-03T13:04:39.791Z\",\"userId\":2}"
println("jsonString:\n\(jsonString)")

func parseJSON(jsonString: String) -> [String: AnyObject]? {
    if let data = jsonString.dataUsingEncoding(NSUTF8StringEncoding) {
        var error: NSError?
        if let json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(0), error: &error) as? [String: AnyObject] {
            return json
        } else if let error = error {
            println("JSON Error: \(error)")
        } else {
            println("Unknown JSON Error")
        }
    }
    return nil
}

let obj = parseJSON(jsonString)
println("obj:\n\(obj!)")
输出:

jsonString: {“id”:“BHZKNJRBUPN9KSC1GEGQTNHJFNWUIFNxpFZUKYXC5IWRDEHUERURRVSDBMZZRVI”,“ttl”:1209600,“创建”:“2015-07-03T13:04:39.791Z”,“用户id”:2}

obj: [创建日期:2015-07-03T13:04:39.791Z,用户id:2,ttl:1209600,id:BHZKNJRBUPN9KSC1GEGQTNHJFNWUIFNxPFZUKYXC5IWRDEHUERURRVSDBMZZRVI]


一些人认为,本课程的内容是创建一个小型的自包含测试或编写单元测试。

必须从
NSURLConnection.sendAsynchronousRequest
完成块调用
parseJSON
方法,而不仅仅是在发出异步请求之后,该点通常没有响应

if data != nil {
    json = NSString(data: data, encoding: NSUTF8StringEncoding) as! String
    println("json: \(json)")

    if let dictionary = parseJSON(jsonString) {
        println("dictionary: \(dictionary)")
   }
}

不清楚JSON字符串的打印位置,在
parseJSON
方法中println()
jsonString
,并添加问题。我认为从performLoginRequestWithURL方法返回的JSON发生了一些问题。我认为错误可能不在于我如何解析它,而在于返回了什么。当我将println(json)向下移动到return json上方时,变量又突然变为空。我同意,问题发生在performLoginRequestWithURL方法中。我认为错误可能不在于我如何解析它,而在于返回了什么。当我将println(json)向下移动到returnjson上方时,变量又突然变为空。如果我在If数据中设置了返回json!=nil block,它表示无法将字符串转换为void。有两件事:打印错误和响应,在响应中将是http
statusCode
,从技术上讲,
状态代码是
NSHTTPURLResponse`的属性,因此您可能需要强制转换。我现在知道为什么会出现错误(请参阅我文章中的编辑部分),但我仍然很困惑。简而言之,我不知道如何从帖子中获取json。总之,我认为我可能需要使用同步请求,但我还没有找到在这种情况下如何使用它的好例子。好主意!我会试试。仍然会遇到如何从整体方法performLoginRequestWithURL返回解析后的JSON的问题。其中返回的任何内容都会出现错误,无法转换为void。您不能。您需要构造代码,以便能够处理稍后的返回。可能会发送
NSNotification
或更新数据模型并请求刷新需要显示的数据模型。是的,异步是比较困难的,但必须为其设计。我想我可以使用实例变量来处理该块中的整个登录请求,而不是向登录操作返回任何内容。
NSArray *jsonObj = [NSJSONSerialization JSONObjectWithData:data
                                                   options:kNilOptions
                                                     error:&err];

if ( err )
{
    // code 3840, data.length = 1 byte, so empty and no error
    if ( NSPropertyListErrorMinimum == err.code )
    {
        return [NSArray array];
    }

    *error = err;
    return nil;
}