如何使用Unicode十六进制值(UTF-16)在Swift中表示字符串

20

我想在Swift中使用十六进制值来编写Unicode字符串。我已经阅读了String和Character的文档,因此我知道可以直接在字符串中使用特殊的Unicode字符,例如以下内容:

var variableString = "Cat‼" // "Cat" + Double Exclamation + cat emoji

但我想使用Unicode代码点来实现它。文档(以及这个问题)展示了如何处理字符,但并不清楚如何处理字符串。

(注意:尽管现在答案对我来说似乎很明显,但只是短时间之前它并不明显。我在下面回答自己的问题,以学习如何做到这一点,并帮助自己理解Unicode术语以及Swift字符和字符串的工作方式。)

2个回答

38

字符

用于形成十六进制代码点的Swift语法为

\u{n}

其中n为最多8位数字的十六进制数。Unicode标量的有效范围为U+0到U+D7FF和U+E000到U+10FFFF(包括边界)。(U+D800至U+DFFF范围是用于代理对,它们本身不是标量,但在UTF-16中用于编码更高值的标量)。

示例:

// The following forms are equivalent. They all produce "C". 
let char1: Character = "\u{43}"
let char2: Character = "\u{0043}"
let char3: Character = "\u{00000043}"

// Higher value Unicode scalars are done similarly
let char4: Character = "\u{203C}" // ‼ (DOUBLE EXCLAMATION MARK character)
let char5: Character = "\u{1F431}" //  (cat emoji)

// Characters can be made up of multiple scalars
let char7: Character = "\u{65}\u{301}" // é = "e" + accent mark
let char8: Character = "\u{65}\u{301}\u{20DD}" // é⃝ = "e" + accent mark + circle

注:

字符串

字符串由字符组成。 以下示例展示了使用十六进制代码点来形成字符串的一些方法。

示例:

var string1 = "\u{0043}\u{0061}\u{0074}\u{203C}\u{1F431}" // Cat‼

// pass an array of characters to a String initializer
let catCharacters: [Character] = ["\u{0043}", "\u{0061}", "\u{0074}", "\u{203C}", "\u{1F431}"] // ["C", "a", "t", "‼", ""]
let string2 = String(catCharacters) // Cat‼

在运行时转换十六进制值

在运行时,您可以将十六进制或 Int 值转换为 CharacterString,方法是先将其转换为 UnicodeScalar

示例:

// hex values
let value0: UInt8  = 0x43     // 67
let value1: UInt16 = 0x203C   // 8252
let value2: UInt32 = 0x1F431  // 128049

// convert hex to UnicodeScalar
let scalar0 = UnicodeScalar(value0)
// make sure that UInt16 and UInt32 form valid Unicode values
guard
    let scalar1 = UnicodeScalar(value1),
    let scalar2 = UnicodeScalar(value2) else {
    return
}

// convert to Character
let character0 = Character(scalar0) // C
let character1 = Character(scalar1) // ‼
let character2 = Character(scalar2) // 

// convert to String
let string0 = String(scalar0) // C
let string1 = String(scalar1) // ‼
let string2 = String(scalar2) // 

// convert hex array to String
let myHexArray = [0x43, 0x61, 0x74, 0x203C, 0x1F431] // an Int array
var myString = ""
for hexValue in myHexArray {
    if let scalar = UnicodeScalar(hexValue) {
        myString.append(Character(scalar))
    }
}
print(myString) // Cat‼

进一步阅读


@Suragch 我有一个Unicode字符\u{0D85}。我该如何获取它的Int值? - Isuru
@Isuru,我在这里重新提出并回答了你的问题:如何在Swift中将Unicode字符转换为Int - Suragch
@Suragch 非常感谢您详细的回答。实际上,我在这个答案中找到了如何做到这一点。但是,仍然很好有一个全面的解释。 - Isuru
@Isuru,请注意你链接的答案中,如果一个Character由多个标量组成,则只返回第一个标量值。其他标量将被忽略。(例如:let myChar: Character = "\u{65}\u{301}" // é - Suragch
@Sebastian,显然我写下这句话时处于某个宇宙中。感谢您的评论。现在转换已经修复为此宇宙。 - Suragch
显示剩余7条评论

3

将你的十六进制代码"0x1F52D"转化为实际的表情符号

let c = 0x1F602

下一步可能是从您的十六进制中获取一个Uint32。
let intEmoji = UnicodeScalar(c!).value

从这里,你可以做类似于以下的事情:
titleLabel.text = String(UnicodeScalar(intEmoji)!)

这里有一个 ""

它也可以使用十六进制范围

let emojiRanges = [
            0x1F600...0x1F636,
            0x1F645...0x1F64F,
            0x1F910...0x1F91F,
            0x1F30D...0x1F52D
        ]

        for range in emojiRanges {
            for i in range {
                let c = UnicodeScalar(i)!.value
                data.append(c)
            }
        }

例如,从您的十六进制范围中获取多个 UInt32


请勿在多个问题中发布相同的答案。如果相同的信息确实回答了两个问题,则应将一个问题(通常是较新的问题)关闭为另一个问题的副本。您可以通过voting to close it as a duplicate来表示这一点,或者如果您没有足够的声望,则raise a flag来指示它是重复的。否则,请确保您将答案调整到问题,并不要只是在多个地方粘贴相同的答案。 - elixenide
制作了这篇介绍如何在Swift中使用Unicode十六进制值显示字符串表情符号的Medium文章。https://medium.com/@kamiFR/how-to-show-emojis-with-strings-in-swift-using-unicode-hexadecimal-values-5093448cd1a9 - Mehdi S.
通常许多问题都可以采用相同的解答方式,当作者这样做时,我会予以支持。 - Sebastian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接