【问题标题】:Convert UTF-8 (Bytes) Emoji Code to Emoji icon as a text将 UTF-8 (Bytes) Emoji Code 转换为 Emoji 图标作为文本
【发布时间】:2018-05-18 10:21:41
【问题描述】:

当他们将表情符号作为字符串发送时,我收到以下字符串作为 WS API 的响应:

let strTemp = "Hii \\xF0\\x9F\\x98\\x81"

我希望它像这样转换为表情符号图标 -> Hii ????

我认为它采用 UTF-8 格式,如下图所示:Image Unicode

我已经尝试使用UTF-8 Decoder在线解码它

我的表情符号成功解码

解码前:

解码后:

但这里的问题是我不知道如何在 Swift 中使用它。

我参考了以下链接,但它对我不起作用。

Swift Encode/decode emojis

任何帮助将不胜感激。

谢谢。

【问题讨论】:

标签: swift emoji


【解决方案1】:

正如您已经给出了转换器工具的链接,该工具显然在进行UTF-8 编码和解码。您有UTF-8 编码字符串,所以这里是UTF8-Decoding 的示例。

Objective-C

const char *ch = [@"Hii \xF0\x9F\x98\x81" cStringUsingEncoding:NSUTF8StringEncoding];
NSString *decode_string = [NSString stringWithUTF8String:ch];
NSLog(@"%@",decode_string);

输出: Hii ?


斯威夫特

我可以在SWift 中将\\xF0\\x9F\\x98\\x81 转换为?。 首先,我将十六进制字符串转换为Data,然后使用UTF-8 编码转换回String

var str = "\\xF0\\x9F\\x98\\x81"
if let data = data(fromHexaStr: str) {
     print(String(data: data, encoding: String.Encoding.utf8) ?? "")
}

输出: ?

下面是我用来将六进制字符串转换为数据的函数。我关注了this answer

func data(fromHexaStr hexaStr: String) -> Data? {
    var data = Data(capacity: hexaStr.characters.count / 2)
    let regex = try! NSRegularExpression(pattern: "[0-9a-f]{1,2}", options: .caseInsensitive)
    regex.enumerateMatches(in: hexaStr, range: NSMakeRange(0, hexaStr.utf16.count)) { match, flags, stop in
        let byteString = (hexaStr as NSString).substring(with: match!.range)
        var num = UInt8(byteString, radix: 16)!
        data.append(&num, count: 1)
    }

    guard data.count > 0 else { return nil }

    return data
}

注意: 上面代码的问题是它只转换了十六进制字符串而不是组合字符串。

最终工作解决方案:SWIFT

我已经通过使用 for 循环而不是 [0-9a-f]{1,2} 正则表达式来做到这一点,因为这也会扫描 81, 9F, Any Two digits number,这显然是错误的。

例如:I have 81 INR \\xF0\\x9F\\x98\\x81

/// This line will convert "F0" into hexa bytes
let byte = UInt8("F0", radix: 16)

我做了一个字符串扩展,我最多检查每 4 个字符是否有前缀 \x 和计数 4,最后两个字符可以通过使用 radix 转换为十六进制字节,如上所述。

extension String {

    func hexaDecoededString() -> String {

        var newData = Data()
        var emojiStr: String = ""
        for char in self.characters {

            let str = String(char)
            if str == "\\" || str.lowercased() == "x" {
                emojiStr.append(str)
            }
            else if emojiStr.hasPrefix("\\x") || emojiStr.hasPrefix("\\X") {
                emojiStr.append(str)
                if emojiStr.count == 4 {
                    /// It can be a hexa value
                    let value = emojiStr.replacingOccurrences(of: "\\x", with: "")
                    if let byte = UInt8(value, radix: 16) {
                        newData.append(byte)
                    }
                    else {
                        newData.append(emojiStr.data(using: .utf8)!)
                    }
                    /// Reset emojiStr
                    emojiStr = ""
                }
            }
            else {
                /// Append the data as it is
                newData.append(str.data(using: .utf8)!)
            }
        }

        let decodedString = String(data: newData, encoding: String.Encoding.utf8)
        return decodedString ?? ""
    }
}

用法:

var hexaStr = "Hi \\xF0\\x9F\\x98\\x81 81"
print(hexaStr.hexaDecoededString())

嗨? 81

hexaStr = "Welcome to SP19!\\xF0\\x9f\\x98\\x81"
print(hexaStr.hexaDecoededString())

欢迎来到 SP19!?

【讨论】:

  • 你能分享一下 Swift 代码吗?我不知道 obj-C。
  • 让我试试!请稍候!
  • 等待你的转化
  • 是的,我正在尝试。实际上没有注意到这是为了快速。
  • 你可以试试 Swiftyfy。当您尝试将 ObjC 代码转换为 Swift 时,这很正常。 objectivec2swift.com/#/converter
【解决方案2】:

我解决了您的问题,但需要做更多工作才能使其通用,这里的问题是您的 Emijo 由 Hex Byte x9F 表示,因此我们必须将此十六进制转换为 utf8 然后将其转换为 @ 987654324@,最后将数据转换为String

最终结果Hii ? 请阅读评论

 let strTemp = "Hii \\xF0\\x9F\\x98\\x81"


            let regex = try! NSRegularExpression(pattern: "[0-9a-f]{1,2}", options: .caseInsensitive)
            // get all matched hex  xF0 , x9f,..etc

            let matches = regex.matches(in: strTemp, options: [], range: NSMakeRange(0, strTemp.count))


            // Data that will hanlde convert hex to UTf8
            var emijoData = Data(capacity: strTemp.count / 2)

            matches.enumerated().forEach { (offset , check) in
                let byteString = (strTemp as NSString).substring(with: check.range)
                var num = UInt8(byteString, radix: 16)!
                emijoData.append(&num, count: 1)
            }

            let subStringEmijo = String.init(data: emijoData, encoding: String.Encoding.utf8)!
            //now we have your emijo text  ? we can replace by its code from string using matched ranges `first` and `last`

            // All range range of  \\xF0\\x9F\\x98\\x81 in "Hii \\xF0\\x9F\\x98\\x81" to replce by your emijo

            if let start = matches.first?.range.location, let end = matches.last?.range.location  , let endLength = matches.last?.range.length {

                let startLocation = start  - 2
                let length = end - startLocation + endLength

                let sub = (strTemp as NSString).substring(with: NSRange.init(location: startLocation, length: length))

                print( strTemp.replacingOccurrences(of: sub, with: subStringEmijo))
              // Hii ?

            }

【讨论】:

  • 您好,感谢您的回答,这对我帮助很大,但问题是它适用于静态字符串“Hii \\xF0\\x9F\\x98\\x81”。如果我在响应中得到动态字符串怎么办。就像 "Welcome to SP19!\\xF0\\x9f\\x98\\x81" 在这种情况下,表情符号正在打印,但应用程序在替换子字符串时崩溃。有什么解决方案让它变得动态。?
  • App崩溃了,因为subStringEmijo没有检查它,这段代码是通用的,你只需要重构它
  • 应用程序在 let sub = (strTemp as NSString).substring(with: NSRange.init(location: startLocation, length: length)) 处崩溃。如果我得到其他字符串
  • 是的,我告诉过你这个想法,你需要配置它,你需要获取编码的 emijo 的所有范围并用解码的 emijo 替换
  • 感谢先生的建议。为您的辛勤工作投票。
猜你喜欢
  • 2021-08-16
  • 2016-10-12
  • 1970-01-01
  • 2021-11-27
  • 2018-05-09
  • 2021-01-28
  • 1970-01-01
  • 2014-09-02
  • 2016-08-18
相关资源
最近更新 更多