Swift - 特殊字符的编码和解码字符串

时间:2016-10-02 15:02:34

标签: swift string encoding utf-8 swift3

这是我的问题:我目前正在开发一个包括即时聊天(使用FCM)的应用程序。 除非我尝试发送像“é”或表情符号这样的特殊字符,否则每件事都有效。 收到的推送通知包含好的字符串但是当讨论保存在服务器上然后重新加载时,我无法读取它们并获得UTF8文本,例如“u00ea”表示“ê”。 我对编码等并不是很了解,但如果你们能帮助我,我会很开心!

以下是我用来发送消息的代码:

    func sendMessage(_ completion: @escaping (_ response: String) -> ()) {

    DispatchQueue.global(qos: .userInitiated).async { () -> Void in
        let urlString = //Server adress
        let url = URL(string: urlString)

        var request = URLRequest(url: url!)
        let set = CharacterSet()
        request.httpMethod = "POST"
        let postString = "Message=" + /*String text to send*/
        request.httpBody = postString.data(using: String.Encoding.utf8)

    let task = URLSession.shared.dataTask(with: request, completionHandler: { (data, response, error) in

        })
        task.resume()
    }
}

非常感谢!

PS:我是新来要求stackoverflow所以不要犹豫,要求更多细节

按Rob的要求编辑: 我发了短信“testéè” 另一部手机通过推送通知收到“测试éè” 当一部手机加载来自服务器的讨论,其中存储了来自服务器的答案。

    [{"content":"test u00e9 u00e8","sender":"103","timestamp":"1475491191"}]

此外,我不是在编写服务器代码,但是那个正在制作Android应用程序的人也可以使用特殊字符。

编辑#2 :我也尝试使用此代码

    var request = URLRequest(url: url!)
        let set = CharacterSet()
        request.httpMethod = "POST"
        let postString = "Message=" + self.message.addingPercentEncoding(withAllowedCharacters: set)!
        let bytesArray = UTF8Encoding.decode(postString)

        request.httpBody = Data(bytes: UnsafePointer<UInt8>(bytesArray), count: bytesArray.count)

它没有任何区别。

非常感谢你的帮助。

4 个答案:

答案 0 :(得分:4)

您希望使用addingPercentEncoding百分比转义字符串。但是不要试图使用像urlQueryAllowed这样的字符集,因为这会让一些关键字符(特别是&+)无法通过。

作为如何正确执行此操作的一个很好的示例,请参阅Alamofire的ParameterEncoding escape例行程序。这是作为扩展实现的再现:

extension String {
    public func addingPercentEncodingForQueryParameter() -> String? {
        return addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed)
    }
}

extension CharacterSet {
    static let urlQueryValueAllowed: CharacterSet = {
        let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
        let subDelimitersToEncode = "!$&'()*+,;="

        var allowed = CharacterSet.urlQueryAllowed
        allowed.remove(charactersIn: generalDelimitersToEncode + subDelimitersToEncode)

        return allowed
    }()
}

然后你可以做类似的事情:

func send(message: String, _ completion: @escaping (_ response: String) -> ()) {
    let urlString = ...
    let url = URL(string: urlString)

    var request = URLRequest(url: url!)
    request.httpMethod = "POST"
    request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
    let postString = "Message=\(message.addingPercentEncodingForQueryParameter()!)"
    request.httpBody = postString.data(using: .utf8)

    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        ...
    }
    task.resume()
}

答案 1 :(得分:1)

好的,我想我有,

正如所建议的,这部分是由于服务器实现。由于其安全性,它过滤了某些字符,这就是它无法正常工作的原因。

我们已经纠正了这个问题,但当讨论从iOS到Android或从Android到iOS时,它仍然不起作用。

非常感谢你的帮助!

这是我的最终代码:

(define (complement f)
  (comp not f)) ; comp returns a procedure always

(define my-even? (complement odd?))
(my-even? 2) ; ==> #t

答案 2 :(得分:0)

我建议您使用Dictionary来存储非 GET 请求的正文(用于 POST PUT 等) ),并在UTF-8中将JSONSerialization用于encoding主体,以将其传递到您httpBody的{​​{1}}。

所以代替:

URLRequest

使用此:

let postString = "Message=" + "Hello, World!"
request.httpBody = postString.data(using: String.Encoding.utf8)

实际上它let bodyDictionary: [String: Any?] = ["Message": "String text to send"] request.httpBody = try? JSONSerialization.data(withJSONObject: bodyDictionary, options: []) 并且需要最少的硬编码,因此可以确保您避免例如此代码中的“消息 = ”。

答案 3 :(得分:-1)

尝试这个! jsonString?.addingPercentEncoding(withAllowedCharacters:.symbols)?? “”