目录
[toc]
Unicode
Swift的String类型是基于Unicode标量建立的,先来介绍一下Unicode和Unicode标量。
人类使用的文字和符号要想被计算机所理解必须要经过编码,Unicode就是其中的一种编码标准。
码点:Unicode标准为世界上几乎所有的书写系统里所使用的每一个字符或符号定义了一个唯一的数字。这个数字叫做码点(code points),以U+xxxx这样的格式写成,格式里的xxxx代表四到六个十六进制的数。例如U+0061表示小写的拉丁字母(LATIN SMALL LETTER A)("a"),U+1F425表示小鸡表情(FRONT-FACING BABY CHICK) ("🐥"),有趣的是,字符的名字比如"FRONT-FACING BABY CHICK"也是Unicode标准的一部分。
编码格式:通过字符到码点之间的映射,人们得以用统一的方式表示符号,但还需要定义另一种编码来确定码点与其存储在内存和硬盘中的值的对应关系。有三种Unicode支持的编码格式:
- UTF-8:表示一个码点需要1~4个八位的码元。利用字符串的utf8属性进行访问。
- UTF-16:用一或两个16位的码元表示一个吗点。利用字符串的utf16属性进行访问。
- 21位的 Unicode 标量值集合,也就是字符串的UTF-32编码格式,用21位的码元表示一个码点。利用字符串的unicodeScalars属性进行访问。
String的可拓展字符群集
每一个String对象都有一个characters: String.CharacterView
属性,代表一个可拓展的字符群。
每一个Swift字符串提供一个CharacterView包含它的全部内容,在CharacterView中,如“é”, “김”, and “🇮🇳”是作为独立的character存在的,这些独立的character可能是由多个Unicode码点组成的。组成独立character的一个或多个码点会被Unicode组合成一个可拓展字符群,由Character类型来表示。CharacterView集合的每一个元素都是一个Character实例。先来看一下可拓展字形群的意思:
可拓展的字形群:一个或多个可生成人类可读字符的Unicode标量的有序排列。比如é即为一个可拓展字形群,它可以用单一的Unicode标量é(LATIN SMALL LETTER E WITH ACUTE, 或者U+00E9)来表示。然而一个标准的字母e(LATIN SMALL LETTER E或者U+0065)加上一个急促重音(COMBINING ACTUE ACCENT,或者U+0301),这样一对标量就表示了同样的字母é。在第一种情况,这个字形群包含一个单一标量;而在第二种情况,它是包含两个标量的字形群。除此之外,还有几个比较特殊的可拓展字符群集如:
let precomposed: Character = "\u{D55C}" // 한
let decomposed: Character = "\u{1112}\u{1161}\u{11AB}" // ᄒ, ᅡ, ᆫ
// precomposed 是 한, decomposed 是 한
let enclosedEAcute: Character = "\u{E9}\u{20DD}"
// enclosedEAcute 是 é⃝
let regionalIndicatorForUS: Character = "\u{1F1FA}\u{1F1F8}"
// regionalIndicatorForUS 是 🇺🇸
CharacterView集合中的元素为Character实例,一个Character实例对应一个可拓展字形群。所以Swift字符串无论是在计算长度(通过character的count属性),还是在进行下标访问,都是以Character,也就是可拓展字形群为最小单位的,所以在Swift字符串眼里é("\u{E9}")与e加 ́("\u{65}\u{301}")是一回事。
但NSString对象是以Unicode码点为最小单位索引和计算长度,所以所示结果与Swift字符串不同。
let str = "e\u{301}" // é
let strLengthOfString = str.characters.count // 1
let strLengthOfNSString = (str as NSString).length // 2
网友评论