【问题标题】:SWIFT: NSURLSession convert data to StringSWIFT:NSURLSession 将数据转换为字符串
【发布时间】:2015-09-21 11:53:24
【问题描述】:

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

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

1)。当我使用 UTF8 编码时,我得到 nil 作为转换后的字符串(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。

想知道我是否遗漏了任何东西,或者最好的方法是什么...谢谢。

【问题讨论】:

    标签: ios objective-c swift


    【解决方案1】:

    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 响应中发送响应编码 标头,那么您只能尝试不同的编码。经常使用 编码是

    • NSUTF8StringEncodingUTF-8 编码,
    • NSWindowsCP1252StringEncodingWindows-1252 编码,
    • NSISOLatin1StringEncoding 用于 ISO-8859-1 编码。

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

    【讨论】:

    • 谢谢 Martin R... 我只是按照您在 LINK 中的建议尝试了这个(让 encodingName = response.textEncodingName)。但是当我检查这个时这是零。不太确定为什么这是零......因此我无法得到你在那里建议的'usedEncoding'......我可以使用'NSASCIIStringEncoding'并完成任务,但是正如你所说的行为没有记录感觉不安全......
    • @JibW:正如我所说,如果服务器不发送使用的编码,那么您必须猜测。您可以尝试列出的三种编码(按此顺序)并使用第一个转换不为零的编码。
    • 嗨,马丁 R,谢谢。最后一件事....我无法理解的是“NSUTF8StringEncoding”在除一种情况外的所有情况下都能正常工作。我能看到的唯一附加字符是“£”。 ASCII 在这种情况下工作而不是 UTF8.... 绝对服务应该在所有情况下使用相同的编码...作为解决方案,我所能做的就是按照您的建议检查 3 种主要类型。
    • @JibW:UTF-8 和 ASCII 编码对于 7 位 ASCII 字符是相同的。像“à”这样的其他字符也会产生同样的问题。
    • @JibW: NSStringEncoding() 只返回值零,这不是有效的编码。它被视为 ASCII 编码,但可能会导致警告,如 “检测到不正确的 NSStringEncoding 值 0x0000。假设为 NSASCIIStringEncoding。将在不久的将来停止这种兼容性映射行为。”
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-29
      • 2015-11-21
      • 2013-10-26
      • 2018-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多