首页 文章

SWIFT:NSURLSession将数据转换为String

提问于
浏览
4

在我的iPhone应用程序(在SWIFT中开发)中,我必须使用https服务(带参数)进行通信,并需要分析响应 .

一切正常,但在某些情况下注意到它没有得到预期的结果...进一步分析我发现这是将服务器响应数据转换为字符串(NSData - > NSString)的问题...

1) . 当我使用 UTF8 编码我得到nil作为转换后的String(responseString)

let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)

2) . 但是使用 ASCII 编码它很好(获取正确的响应服务器提供)

let responseString = NSString(data: data, encoding: NSASCIIStringEncoding)

Following is a full sample code I am trying ...

let myUrl = NSURL(string: "https://myurl.com/myservice.asp")
    let request = NSMutableURLRequest(URL: myUrl!)

    request.HTTPMethod = "POST"
    request.timeoutInterval = 55.0
    let postString = "paramone=\(para1)&paramtwo=\(para2)&paramthree=\(para3)"

    // NOTE: Works ok with ASCII AND UTF8 both encoding types at this point...
    // request.HTTPBody = postString.dataUsingEncoding(NSASCIIStringEncoding)
    request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)

    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in

        if (error != nil)
        {
            println("Error: \(error)")
            println("Description: \(error.description)")
            println("Domain     : \(error.domain)")
            println("Error code : \(error.code)")
        }
        else
        {
            //???? => ENCODING PROBLEM
            // let responseString = NSString(data: data, encoding: NSASCIIStringEncoding)
            let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)

            println("Response: \(responseString)")
        }
    }
    task.resume()

我遇到了其他几个解释同样问题的人......但不确定用ASCII而不是UTF8是否合适...

另外我无法理解响应包含'£'符号并且可以使用ASCII编码(尽管'''不是ASCII字符集),但不是UTF8 .

想听听我是否遗漏了什么,或者最好的方式是什么......谢谢 .

2 回答

  • 5

    NSASCIIStringEncoding 被记录为ASCII值0 .. 127的严格7位编码 . 但是,实验表明,当将 NSData 解码为 (NS)String 时,它接受任意数据并将字节0 .. 255解释为Unicode字符U 0000 .. U 00FF . 所以在解码时, NSASCIIStringEncoding 的行为与 NSISOLatin1StringEncoding 完全相同:

    let bytes = (0 ..< 256).map { UInt8($0) }
    let data = NSData(bytes: bytes, length: bytes.count)
    
    let s1 = String(data: data, encoding: NSASCIIStringEncoding)!
    let s2 = String(data: data, encoding: NSISOLatin1StringEncoding)!
    print(s1 == s2) // true
    

    这可以解释为什么像“£”这样的字符即使不在ASCII字符集中也能正确解码 .

    但请注意,这种行为(据我所知)没有记录,所以你不应该依赖它 . 将 (NS)String 编码为 NSData 时,这也不起作用:

    let d1 = s1.dataUsingEncoding(NSASCIIStringEncoding) // nil
    

    如果服务器发送带有 Content-Type = charset=... 字段的HTTP响应标头,则可以自动检测编码,请参阅https://stackoverflow.com/a/32051684/1187415 .

    如果服务器没有在HTTP响应头中发送响应编码,那么您只能尝试不同的编码 . 经常使用的编码是

    对于UTF-8编码

    • NSUTF8StringEncoding

    • NSWindowsCP1252StringEncoding 用于Windows-1252编码,
      629 NSISOLatin1StringEncoding 用于ISO-8859-1编码 .

    还有一个 NSString 方法可以检测使用的编码,但这需要您先将数据写入文件,请参阅Convert TXT File of Unknown Encoding to String .

  • 4

    @JibW此代码将帮助您分析响应并易于理解...根据您的要求进行一些其他更改 .

    let URL = NSURL(string: "Paste your url here")!
        var request = NSMutableURLRequest(URL: URL)
        var session = NSURLSession.sharedSession()
        request.HTTPMethod = "POST"
        request.timeInterval = 55.0
        var error: NSError?
        request.HTTPBody = NSJSONSerialization.dataWithJSONObject(parameters, options: nil, error: &error)
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.addValue("application/json", forHTTPHeaderField: "Accept")
    
    
        var data: NSData!
        var response: NSURLResponse!
    
        var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
    
            var httpResponse = response as! NSHTTPURLResponse
            println("\(httpResponse.statusCode)")
    
            var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
            println("Body: \(strData)")
    
             var err: NSError?
            var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as? NSDictionary
    
             if(err != nil) {
                println(err!.localizedDescription)
                let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
                println("Error could not parse JSON: '\(jsonStr)'")
            }
    
            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
                    var success = parseJSON["success"] as? Int
                    println("Succes: \(success)")
                }
    
                else {
    
                    // Woa, okay the json object was nil, something went worng. Maybe the server isn't running?
                    let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
                    println("Error could not parse JSON: \(jsonStr)")
                }
            }
        })
    
        task.resume()
    

相关问题