SWIFT:NSURLSession将数据转换为String

时间:2015-09-21 11:53:25

标签: ios objective-c swift

在我的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)

以下是我正在尝试的完整示例代码 ...

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

我偶然发现其他几个POSTS解释了同样的问题...但不确定使用ASCII而不是UTF8是否合适......

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

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

2 个答案:

答案 0 :(得分:6)

NSASCIIStringEncoding 记录作为严格的7位编码 对于ASCII值0 .. 127.但是,实验表明何时 解码 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)StringNSData

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

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

如果服务器未在HTTP响应中发送响应编码 标题然后你只能尝试不同的编码。经常使用 编码是

  • NSUTF8StringEncoding用于UTF-8编码,
  • NSWindowsCP1252StringEncoding用于Windows-1252编码,
  • NSISOLatin1StringEncoding用于ISO-8859-1编码。

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

答案 1 :(得分: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()