* 修改第二章部分细节

* update string chapter

* fix some issues

* fix some issues

* fix some issues
This commit is contained in:
Karsa Wu
2018-12-16 23:52:02 +08:00
committed by Jie Liang
parent 2c2097e940
commit 72e24680a0

View File

@ -1,16 +1,14 @@
# 字符串和字符
*字符串*是是一系列字符的集合,例如 `"hello, world"``"albatross"`。Swift 的字符串通过 `String` 类型来表示。
一个 `String` 的内容可以用许多方式读取,包括作为一个 `Character` 值的集合。
*字符串*是是一系列字符的集合,例如 `"hello, world"``"albatross"`。Swift 的字符串通过 `String` 类型来表示。`String` 内容的访问方式有多种,例如以 `Character` 值的集合。
Swift 的 `String``Character` 类型提供了快速兼容 Unicode 的方式供你的代码使用。创建和操作字符串的语法与 C 语言中字符串操作相似,轻量并且易读。字符串连接操作只需要简单地通过 `+` 符号将两个字符串相连即可。与 Swift 中其他值一样,能否更改字符串的值,取决于其被定义为常量还是变量。你可以在字符串内插过程中使用字符串插入常量、变量、字面量表达成更长的字符串,这样可以很容易的创建自定义的字符串值,进行展示、存储以及打印
Swift 的 `String``Character` 类型提供了一种快速兼容 Unicode 的方式来处理代码中的文本内容。创建和操作字符串的语法与 C 语言中字符串操作相似,轻量并且易读。通过 `+` 符号就可以非常简单的实现两个字符串的拼接操作。与 Swift 中其他值一样,能否更改字符串的值,取决于其被定义为常量还是变量。你可以在已有字符串插入常量、变量、字面量表达式从而形成更长的字符串,这一过程也被成为字符串插值。尤其是在为显示、存储和打印创建自定义字符串值时,字符串插值操作尤其有用
尽管语法简易,但 `String` 类型是一种快速现代化的字符串实现
每一个字符串都是由编码无关的 Unicode 字符组成,并支持访问字符的多种 Unicode 表示形式。
尽管语法简易,但 Swift 中的 `String` 类型的实现却很快速现代化。每一个字符串都是由编码无关的 Unicode 字符组成,并支持访问字符的多种 Unicode 表示形式
> 注意
>
> Swift 的 `String` 类型与 Foundation `NSString` 类进行了无缝桥接。Foundation 也可以对 `String` 进行扩展,暴露在 `NSString` 中定义的方法。 这意味着,如果你在 `String` 中调用些 `NSString` 的方法,将不用进行转换。
> Swift 的 `String` 类型与 Foundation `NSString` 类进行了无缝桥接。Foundation 对 `String` 进行扩展使其可以访问 `NSString` 类型中定义的方法。这意味着调用些 `NSString` 的方法,你无需进行任何类型转换。
>
> 更多关于在 Foundation 和 Cocoa 中使用 `String` 的信息请查看 *[Using Swift with Cocoa and Objective-C (Swift 4)](https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/WorkingWithCocoaDataTypes.html#//apple_ref/doc/uid/TP40014216-CH6)*。
@ -25,7 +23,7 @@ Swift 的 `String` 和 `Character` 类型提供了快速和兼容 Unicode 的方
let someString = "Some string literal value"
```
注意 `someString` 常量通过字符串字面量进行初始化Swift 会推断该常量为 `String` 类型
注意Swift 之所以推断 `someString` 常量字符串类型,是因为它使用了字面量方式进行初始化。
<a name="multiline_string_literals"></a>
### 多行字符串字面量
@ -120,7 +118,7 @@ var anotherEmptyString = String() // 初始化方法
// 两个字符串均为空并等价。
```
可以通过检查 `Bool` 类型的 `isEmpty` 属性来判断该字符串是否为空:
可以通过检查 `Bool` 类型的 `isEmpty` 属性来判断该字符串是否为空:
```swift
if emptyString.isEmpty {
@ -132,7 +130,7 @@ if emptyString.isEmpty {
<a name="string_mutability"></a>
## 字符串可变性
可以通过将一个特定字符串分配给一个变量来对其进行修改,或者分配给一个常量来保证其不会被修改:
可以通过将一个特定字符串分配给一个变量来对其进行修改,或者分配给一个常量来保证其不会被修改:
```swift
var variableString = "Horse"
@ -146,26 +144,21 @@ constantString += " and another Highlander"
> 注意
>
> 在 Objective-C 和 Cocoa 中,需要通过选择两个不同的类(`NSString` 和 `NSMutableString`)来指定字符串是否可以被修改。
> 在 Objective-C 和 Cocoa 中,需要通过选择两个不同的类(`NSString` 和 `NSMutableString`)来指定字符串是否可以被修改。
<a name="strings_are_value_types"></a>
## 字符串是值类型
Swift `String` 类型是*值类型*。
如果您创建了一个新的字符串,那么当其进行常量、变量赋值操作,或在函数/方法中传递时,会进行值拷贝。
任何情况下,都会对已有字符串值创建新副本,并对该新副本进行传递或赋值操作。
值类型在 [结构体和枚举是值类型](./09_Classes_and_Structures.html#structures_and_enumerations_are_value_types) 中进行了详细描述。
Swift `String` 类型是*值类型*。如果你创建了一个新的字符串,那么当其进行常量、变量赋值操作,或在函数/方法中传递时,会进行值拷贝。在前述任一情况下,都会对已有字符串值创建新副本,并对该新副本而非原始字符串进行传递或赋值操作。值类型在 [结构体和枚举是值类型](./09_Classes_and_Structures.html#structures_and_enumerations_are_value_types) 中进行了详细描述。
Swift 默认字符串拷贝的方式保证了在函数/方法传递的字符串的值
很明显无论该值来自于哪里,都是您独自拥有的。
您可以确信传递的字符串不会被修改,除非你自己去修改它。
Swift 默认拷贝字符串的行为保证了在函数/方法向你传递的字符串所属权属于你,无论该值来自于哪里。你可以确信传递的字符串不会被修改,除非你自己去修改它
在实际编译时Swift 编译器会优化字符串的使用,使实际的复制只发生在绝对必要的情况下,这意味着将字符串作为值类型的同时可以获得极高的性能。
在实际编译时Swift 编译器会优化字符串的使用,使实际的复制只发生在绝对必要的情况下,这意味着将字符串作为值类型的同时可以获得极高的性能。
<a name="working_with_characters"></a>
## 使用字符
可通过 `for-in` 循环来遍历字符串,获取字符串中每一个字符的值:
可通过 `for-in` 循环来遍历字符串,获取字符串中每一个字符的值:
```swift
for character in "Dog!🐶" {
@ -207,7 +200,7 @@ var welcome = string1 + string2
// welcome 现在等于 "hello there"
```
也可以通过加法赋值运算符(`+=`)将一个字符串添加到一个已经存在字符串变量上:
也可以通过加法赋值运算符(`+=`)将一个字符串添加到一个已经存在字符串变量上:
```swift
var instruction = "look over"
@ -215,7 +208,7 @@ instruction += string2
// instruction 现在等于 "look over there"
```
可以用 `append()` 方法将一个字符附加到一个字符串变量的尾部:
可以用 `append()` 方法将一个字符附加到一个字符串变量的尾部:
```swift
let exclamationMark: Character = "!"
@ -225,7 +218,7 @@ welcome.append(exclamationMark)
> 注意
>
> 不能将一个字符串或者字符添加到一个已经存在的字符变量上,因为字符变量只能包含一个字符。
> 不能将一个字符串或者字符添加到一个已经存在的字符变量上,因为字符变量只能包含一个字符。
如果你需要使用多行字符串字面量来拼接字符串,并且你需要字符串每一行都以换行符结尾,包括最后一行:
@ -259,8 +252,7 @@ print(goodStart + end)
<a name="string_interpolation"></a>
## 字符串插值
*字符串插值*是一种构建新字符串的方式,可以在其中包含常量、变量、字面量和表达式。**字符串字面量**和**多行字符串字面量**都可以使用字符串插值。
您插入的字符串字面量的每一项都在以反斜线为前缀的圆括号中:
*字符串插值*是一种构建新字符串的方式,可以在其中包含常量、变量、字面量和表达式。**字符串字面量**和**多行字符串字面量**都可以使用字符串插值。你插入的字符串字面量的每一项都在以反斜线为前缀的圆括号中:
```swift
let multiplier = 3
@ -268,12 +260,9 @@ let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
// message 是 "3 times 2.5 is 7.5"
```
在上面的例子中,`multiplier` 作为 `\(multiplier)` 被插入到一个字符串常量量中。
当创建字符串执行插值计算时此占位符会被替换为 `multiplier` 实际的值。
在上面的例子中,`multiplier` 作为 `\(multiplier)` 被插入到一个字符串常量量中。当创建字符串执行插值计算时此占位符会被替换为 `multiplier` 实际的值。
`multiplier` 的值也作为字符串中后面表达式的一部分。
该表达式计算 `Double(multiplier) * 2.5` 的值并将结果(`7.5`)插入到字符串中。
在这个例子中,表达式写为 `\(Double(multiplier) * 2.5)` 并包含在字符串字面量中。
`multiplier` 的值也作为字符串中后面表达式的一部分。该表达式计算 `Double(multiplier) * 2.5` 的值并将结果(`7.5`)插入到字符串中。在这个例子中,表达式写为 `\(Double(multiplier) * 2.5)` 并包含在字符串字面量中。
> 注意
>
@ -282,34 +271,24 @@ let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
<a name="unicode"></a>
## Unicode
*Unicode*是一个国际标准,用于文本的编码和表示
它使您可以用标准格式表示来自任意语言几乎所有的字符,并能够对文本文件或网页这样的外部资源中的字符进行读写操作。
Swift 的 `String``Character` 类型是完全兼容 Unicode 标准的。
*Unicode*是一个用于在不同书写系统中对文本进行编码、表示和处理的国际标准。它使你可以用标准格式表示来自任意语言几乎所有的字符并能够对文本文件或网页这样的外部资源中的字符进行读写操作。Swift 的 `String``Character` 类型是完全兼容 Unicode 标准的
<a name="unicode_scalars"></a>
### Unicode 标量
Swift 的 `String` 类型是基于 *Unicode 标量* 建立的。
Unicode 标量是对应字符或者修饰符的唯一的21位数字例如 `U+0061` 表示小写的拉丁字母(`LATIN SMALL LETTER A`"`a`"`U+1F425` 表示小鸡表情(`FRONT-FACING BABY CHICK`"`🐥`")。
Swift 的 `String` 类型是基于 *Unicode 标量* 建立的。Unicode 标量是对应字符或者修饰符的唯一的 21 位数字,例如 `U+0061` 表示小写的拉丁字母(`LATIN SMALL LETTER A`"`a`"`U+1F425` 表示小鸡表情(`FRONT-FACING BABY CHICK`"`🐥`")。
> 注意
>
> Unicode *码位code poing* 的范围是 `U+0000` 到 `U+D7FF` 或者 `U+E000` 到 `U+10FFFF`。Unicode 标量不包括 Unicode *代理项surrogate pair* 码位,其码位范围是 `U+D800` 到 `U+DFFF`。
注意不是所有的21位 Unicode 标量都代表一个字符,因为有一些标量是留作未来分配的。已经代表一个典型字符的标量都有自己的名字,例如上面例子中的 `LATIN SMALL LETTER A``FRONT-FACING BABY CHICK`
<a name="special_characters_in_string_literals"></a>
请注意,并非所有 21 位 Unicode 标量值都分配给字符,某些标量被保留用于将来分配或用于 UTF-16 编码。已分配的标量值通常也有一个名称,例如上面示例中的 LATIN SMALL LETTER A 和 FRONT-FACING BABY CHICK。
<a name="extended_grapheme_clusters"></a>
### 可扩展的字形群集
每一个 Swift 的 `Character` 类型代表一个*可扩展的字形群*。
一个可扩展的字形群是一个或多个可生成人类可读的字符 Unicode 标量的有序排列。
每一个 Swift 的 `Character` 类型代表一个*可扩展的字形群*。而一个可扩展的字形群构成了人类可读的单个字符,它由一个或多个(当组合时) Unicode 标量的序列组成。
举个例子,字母 `é` 可以用单一的 Unicode 标量 `é`(`LATIN SMALL LETTER E WITH ACUTE`, 或者 `U+00E9`)来表示。然而一个标准的字母 `e`(`LATIN SMALL LETTER E` 或者 `U+0065`) 加上一个急促重音(`COMBINING ACTUE ACCENT`)的标量(`U+0301`),这样一对标量就表示了同样的字母 `é`
这个急促重音的标量形象的将 `e` 转换成了 `é`
在这两种情况中,字母 `é` 代表了一个单一的 Swift 的 `Character` 值,同时代表了一个可扩展的字形群。
在第一种情况,这个字形群包含一个单一标量;而在第二种情况,它是包含两个标量的字形群:
在这两种情况中,字母 `é` 代表了一个单一的 Swift 的 `Character` 值,同时代表了一个可扩展的字形群。在第一种情况,这个字形群包含一个单一标量;而在第二种情况,它是包含两个标量的字形群:
```swift
let eAcute: Character = "\u{E9}" // é
@ -317,9 +296,7 @@ let combinedEAcute: Character = "\u{65}\u{301}" // e 后面加上 ́
// eAcute 是 é, combinedEAcute 是 é
```
可扩展的字符群集是一个灵活的方法,用许多复杂的脚本字符表示单一的 `Character`
例如,来自朝鲜语字母表的韩语音节能表示为组合或分解的有序排列。
在 Swift 都会表示为同一个单一的 `Character` 值:
可扩展的字集是一个许多复杂的脚本字符表示为单个字符值的灵活方式。例如,来自朝鲜语字母表的韩语音节能表示为组合或分解的有序排列。在 Swift 都会表示为同一个单一的 `Character`
```swift
let precomposed: Character = "\u{D55C}" // 한
@ -369,7 +346,7 @@ print("the number of characters in \(word) is \(word.count)")
> 注意
>
> 可扩展的字符群集可以组成一个或者多个 Unicode 标量。这意味着不同的字符以及相同字符的不同表示方式可能需要不同数量的内存空间来存储。所以 Swift 中的字符在一个字符串中并不一定占用相同的内存空间数量。因此在没有获取字符串的可扩展的字符群的范围时候,就不能计算出字符串的字符数量。如果正在处理一个长字符串,需要注意 `count` 属性必须遍历全部的 Unicode 标量,来确定字符串的字符数量。
> 可扩展的字符群集可以组成一个或者多个 Unicode 标量。这意味着不同的字符以及相同字符的不同表示方式可能需要不同数量的内存空间来存储。所以 Swift 中的字符在一个字符串中并不一定占用相同的内存空间数量。因此在没有获取字符串的可扩展的字符群的范围时候,就不能计算出字符串的字符数量。如果正在处理一个长字符串,需要注意 `count` 属性必须遍历全部的 Unicode 标量,来确定字符串的字符数量。
>
> 另外需要注意的是通过 `count` 属性返回的字符数量并不总是与包含相同字符的 `NSString` 的 `length` 属性相同。`NSString` 的 `length` 属性是利用 UTF-16 表示的十六位代码单元数字,而不是 Unicode 可扩展的字符群集。
@ -387,7 +364,7 @@ print("the number of characters in \(word) is \(word.count)")
使用 `startIndex` 属性可以获取一个 `String` 的第一个 `Character` 的索引。使用 `endIndex` 属性可以获取最后一个 `Character` 的后一个位置的索引。因此,`endIndex` 属性不能作为一个字符串的有效下标。如果 `String` 是空串,`startIndex``endIndex` 是相等的。
通过调用 `String``index(before:)``index(after:)` 方法,可以立即得到前面或后面的一个索引。还可以通过调用 `index(_:offsetBy:)` 方法来获取对应偏移量的索引,这种方式可以避免多次调用 `index(before:)``index(after:)` 方法。
通过调用 `String``index(before:)``index(after:)` 方法,可以立即得到前面或后面的一个索引。还可以通过调用 `index(_:offsetBy:)` 方法来获取对应偏移量的索引,这种方式可以避免多次调用 `index(before:)``index(after:)` 方法。
你可以使用下标语法来访问 `String` 特定索引的 `Character`
@ -422,7 +399,7 @@ for index in greeting.indices {
> 注意
>
> 可以使用 `startIndex` 和 `endIndex` 属性或者 `index(before:)` 、`index(after:)` 和 `index(_:offsetBy:)` 方法在任意一个确认的并遵循 `Collection` 协议的类型里面,如上文所示是使用在 `String` 中,也可以使用在 `Array`、`Dictionary` 和 `Set` 中。
> 可以使用 `startIndex` 和 `endIndex` 属性或者 `index(before:)` 、`index(after:)` 和 `index(_:offsetBy:)` 方法在任意一个确认的并遵循 `Collection` 协议的类型里面,如上文所示是使用在 `String` 中,也可以使用在 `Array`、`Dictionary` 和 `Set` 中。
<a name="inserting_and_removing"></a>
### 插入和删除
@ -451,7 +428,7 @@ welcome.removeSubrange(range)
> 注意
>
> 可以使用 `insert(_:at:)`、`insert(contentsOf:at:)`、`remove(at:)` 和 `removeSubrange(_:)` 方法在任意一个确认的并遵循 `RangeReplaceableCollection` 协议的类型里面,如上文所示是使用在 `String` 中,也可以使用在 `Array`、`Dictionary` 和 `Set` 中。
> 可以使用 `insert(_:at:)`、`insert(contentsOf:at:)`、`remove(at:)` 和 `removeSubrange(_:)` 方法在任意一个确认的并遵循 `RangeReplaceableCollection` 协议的类型里面,如上文所示是使用在 `String` 中,也可以使用在 `Array`、`Dictionary` 和 `Set` 中。
<a name="substrings"></a>
## 子字符串
@ -497,7 +474,7 @@ if quotation == sameQuotation {
// 打印输出 "These two strings are considered equal"
```
如果两个字符串(或者两个字符)的可扩展的字形群集是标准相等,那就认为它们是相等的。在这个情况下,即使可扩展的字形群集是有不同的 Unicode 标量构成的,只要它们有同样的语言意义和外观,就认为它们标准相等。
如果两个字符串(或者两个字符)的可扩展的字形群集是标准相等,那就认为它们是相等的。只要可扩展的字形群集有同样的语言意义和外观认为它们标准相等,即使它们是由不同的 Unicode 标量构成
例如,`LATIN SMALL LETTER E WITH ACUTE`(`U+00E9`)就是标准相等于 `LATIN SMALL LETTER E`(`U+0065`)后面加上 `COMBINING ACUTE ACCENT`(`U+0301`)。这两个字符群集都是表示字符 `é` 的有效方式,所以它们被认为是标准相等的:
@ -554,7 +531,7 @@ let romeoAndJuliet = [
]
```
可以调用 `hasPrefix(_:)` 方法来计算话剧中第一幕的场景数:
可以调用 `hasPrefix(_:)` 方法来计算话剧中第一幕的场景数:
```swift
var act1SceneCount = 0
@ -567,7 +544,7 @@ print("There are \(act1SceneCount) scenes in Act 1")
// 打印输出 "There are 5 scenes in Act 1"
```
相似地,可以用 `hasSuffix(_:)` 方法来计算发生在不同地方的场景数:
相似地,可以用 `hasSuffix(_:)` 方法来计算发生在不同地方的场景数:
```swift
var mansionCount = 0
@ -590,17 +567,15 @@ print("\(mansionCount) mansion scenes; \(cellCount) cell scenes")
<a name="unicode_representations_of_strings"></a>
## 字符串的 Unicode 表示形式
当一个 Unicode 字符串被写进文本文件或者其他储存时,字符串中的 Unicode 标量会用 Unicode 定义的几种 `编码格式`encoding forms编码。每一个字符串中的小块编码都被称 `代码单元`code units。这些包括 UTF-8 编码格式(编码字符串为8位的代码单元), UTF-16 编码格式编码字符串位16位的代码单元以及 UTF-32 编码格式编码字符串32位的代码单元
当一个 Unicode 字符串被写进文本文件或者其他储存时,字符串中的 Unicode 标量会用 Unicode 定义的几种 `编码格式`encoding forms编码。每一个字符串中的小块编码都被称 `代码单元`code units。这些包括 UTF-8 编码格式(编码字符串为 8 位的代码单元), UTF-16 编码格式(编码字符串位 16 位的代码单元),以及 UTF-32 编码格式编码字符串32位的代码单元
Swift 提供了几种不同的方式来访问字符串的 Unicode 表示形式。
您可以利用 `for-in` 来对字符串进行遍历,从而以 Unicode 可扩展的字符群集的方式访问每一个 `Character` 值。
该过程在 [使用字符](#working_with_characters) 中进行了描述。
Swift 提供了几种不同的方式来访问字符串的 Unicode 表示形式。你可以利用 `for-in` 来对字符串进行遍历,从而以 Unicode 可扩展的字符群集的方式访问每一个 `Character` 值。该过程在 [使用字符](#working_with_characters) 中进行了描述。
另外,能够以其他三种 Unicode 兼容的方式访问字符串的值:
* UTF-8 代码单元集合(利用字符串的 `utf8` 属性进行访问)
* UTF-16 代码单元集合(利用字符串的 `utf16` 属性进行访问)
* 21位的 Unicode 标量值集合,也就是字符串的 UTF-32 编码格式(利用字符串的 `unicodeScalars` 属性进行访问)
* 21 位的 Unicode 标量值集合,也就是字符串的 UTF-32 编码格式(利用字符串的 `unicodeScalars` 属性进行访问)
下面由 `D`,`o`,`g`,`‼`(`DOUBLE EXCLAMATION MARK`, Unicode 标量 `U+203C`)和 `🐶`(`DOG FACE`Unicode 标量为 `U+1F436`)组成的字符串中的每一个字符代表着一种不同的表示:
@ -611,8 +586,7 @@ let dogString = "Dog‼🐶"
<a name="UTF-8_representation"></a>
### UTF-8 表示
可以通过遍历 `String``utf8` 属性来访问它的 `UTF-8` 表示。
其为 `String.UTF8View` 类型的属性,`UTF8View` 是无符号8位`UInt8`)值的集合,每一个 `UInt8` 值都是一个字符的 UTF-8 表示:
可以通过遍历 `String``utf8` 属性来访问它的 `UTF-8` 表示。其为 `String.UTF8View` 类型的属性,`UTF8View` 是无符号 8 位(`UInt8`)值的集合,每一个 `UInt8` 值都是一个字符的 UTF-8 表示:
<table style='text-align:center'>
<tr height="77">
@ -659,15 +633,12 @@ print("")
// 68 111 103 226 128 188 240 159 144 182
```
上面的例子中前三个10进制 `codeUnit` 值(`68``111``103`)代表了字符 `D``o``g`,它们的 UTF-8 表示与 ASCII 表示相同。
接下来的三个10进制 `codeUnit` 值(`226``128``188`)是 `DOUBLE EXCLAMATION MARK` 的3字节 UTF-8 表示。
最后的四个 `codeUnit` 值(`240``159``144``182`)是 `DOG FACE` 的4字节 UTF-8 表示。
上面的例子中,前三个 10 进制 `codeUnit` 值(`68``111``103`)代表了字符 `D``o``g`,它们的 UTF-8 表示与 ASCII 表示相同。接下来的三个 10 进制 `codeUnit` 值(`226``128``188`)是 `DOUBLE EXCLAMATION MARK` 的3字节 UTF-8 表示。最后的四个 `codeUnit` 值(`240``159``144``182`)是 `DOG FACE` 的4字节 UTF-8 表示。
<a name="UTF-16_representation"></a>
### UTF-16 表示
可以通过遍历 `String``utf16` 属性来访问它的 `UTF-16` 表示。
其为 `String.UTF16View` 类型的属性,`UTF16View` 是无符号16位`UInt16`)值的集合,每一个 `UInt16` 都是一个字符的 UTF-16 表示:
可以通过遍历 `String``utf16` 属性来访问它的 `UTF-16` 表示。其为 `String.UTF16View` 类型的属性,`UTF16View` 是无符号16位`UInt16`)值的集合,每一个 `UInt16` 都是一个字符的 UTF-16 表示:
<table style='text-align:center'>
<tr height="77">
@ -710,17 +681,14 @@ print("")
第四个 `codeUnit` 值(`8252`)是一个等于十六进制 `203C` 的的十进制值。这个代表了 `DOUBLE EXCLAMATION MARK` 字符的 Unicode 标量值 `U+203C`。这个字符在 UTF-16 中可以用一个代码单元表示。
第五和第六个 `codeUnit` 值(`55357``56374`)是 `DOG FACE` 字符的 UTF-16 表示。
第一个值为 `U+D83D`(十进制值为 `55357`),第二个值为 `U+DC36`(十进制值为 `56374`)。
第五和第六个 `codeUnit` 值(`55357``56374`)是 `DOG FACE` 字符的 UTF-16 表示。第一个值为 `U+D83D`(十进制值为 `55357`),第二个值为 `U+DC36`(十进制值为 `56374`)。
<a name="unicode_scalars_representation"></a>
### Unicode 标量表示
可以通过遍历 `String` 值的 `unicodeScalars` 属性来访问它的 Unicode 标量表示。
其为 `UnicodeScalarView` 类型的属性,`UnicodeScalarView``UnicodeScalar` 类型的值的集合。
`UnicodeScalar` 是21位的 Unicode 代码点。
可以通过遍历 `String` 值的 `unicodeScalars` 属性来访问它的 Unicode 标量表示。其为 `UnicodeScalarView` 类型的属性,`UnicodeScalarView``UnicodeScalar` 类型的值的集合。
每一个 `UnicodeScalar` 拥有一个 `value` 属性可以返回对应的21位数值`UInt32` 来表示:
每一个 `UnicodeScalar` 拥有一个 `value` 属性,可以返回对应的 21 位数值,用 `UInt32` 来表示:
<table style='text-align:center'>
<tr height="77">