Merge pull request #59 from wh1100717/develop

Refine: Strings && Characters
This commit is contained in:
梁杰
2014-06-08 15:46:11 +08:00

View File

@ -14,31 +14,36 @@
- 字符串大小写 - 字符串大小写
- Unicode - Unicode
**String** 是一个有序的字符集合,例如 "hello, world", "albatross"。 ---
Swift 字符串通过 **String** 类型来表示,也可以表示为 **Character** 类型值的集合。
**String** 是例如 "hello, world", "海贼王" 这样的有序的 **Character** (字符) 类型的值的集合,通过 **String** 类型来表示。
Swift 的 **String****Character** 类型提供了一个快速的,兼容 Unicode 的方式来处理代码中的文本信息。 Swift 的 **String****Character** 类型提供了一个快速的,兼容 Unicode 的方式来处理代码中的文本信息。
创建和操作字符串的语法与 C的操作方式相似,轻量并且易读。 创建和操作字符串的语法与 C 语言中字符串操作相似,轻量并且易读。
字符串连接操作只需要简单地通过 `+` 号将两个字符串相连即可。 字符串连接操作只需要简单地通过 `+` 号将两个字符串相连即可。
与 Swift 中其他值一样,能否更改字符串的值,取决于其被定义为常量还是变量。 与 Swift 中其他值一样,能否更改字符串的值,取决于其被定义为常量还是变量。
尽管语法简易,但 **String** 类型是一种快速、现代化的字符串实现。 尽管语法简易,但 **String** 类型是一种快速、现代化的字符串实现。
每一个字符串都是由独立编码的 Unicode 字符组成,并提供了用于访问这些字符在不同Unicode表示的支持。 每一个字符串都是由独立编码的 Unicode 字符组成,并提供了不同 Unicode 表示 (representations) 来访问这些字符的支持。
**String** 也可以用于在常量、变量、字面量和表达式中进行字符串插值,这使得创建用于展示、存储和打印的字符串变得轻松自如 Swift可以在常量、变量、字面量和表达式中进行字符串插值操作,可以轻松创建用于展示、存储和打印的自定义字符串。
> 注意: > 注意:
> >
> Swift 的 **String** 类型与 Foundation NSString 类进行了无缝桥接。 > Swift 的 **String** 类型与 Foundation NSString 类进行了无缝桥接。
> 如果您利用 Cocoa 或 Cocoa Touch 中的 Foundation 框架进行工作,整个 NSString API 都可以调用您创建的任意 String 类型的值,您额外还可以在任意 API 中使用本章介绍的 **String** 特性 > 如果您利用 Cocoa 或 Cocoa Touch 中的 Foundation 框架进行工作。
> 您也可以在任意要求传入NSString 实例作为参数的 API 中使用 **String** 类型的值进行替换 > 所有 **NSString** API 都可以调用您创建的任意 **String** 类型的值。
> 除此之外,还可以使用本章介绍的 **String** 特性。
> 您也可以在任意要求传入 **NSString** 实例作为参数的 API 中使用 **String** 类型的值作为替代。
> >
>更多关于在 Foundation 和 Cocoa 中使用 **String** 的信息请查看 [Using Swift with Cocoa and Objective-C](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/index.html#//apple_ref/doc/uid/TP40014216)。 >更多关于在 Foundation 和 Cocoa 中使用 **String** 的信息请查看 [Using Swift with Cocoa and Objective-C](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/index.html#//apple_ref/doc/uid/TP40014216)。
---
### 字符串字面量 ### 字符串字面量
您可以在您的代码中包含一段预定义的字符串值作为字符串字面量。 您可以在您的代码中包含一段预定义的字符串值作为字符串字面量。
字符串字面量是由双引号包裹着的具有固定顺序的文本字符集。 字符串字面量是由双引号 ("") 包裹着的具有固定顺序的文本字符集。
字符串字面量可以用于为常量和变量提供初始值。 字符串字面量可以用于为常量和变量提供初始值。
@ -48,47 +53,51 @@ let someString = "Some string literal value"
> 注意: > 注意:
> >
> `someString` 变量通过字符串字面量进行初始化Swift 因此推断为 **String** 类型。 > `someString` 变量通过字符串字面量进行初始化Swift 因此推断该变量为 **String** 类型。
字符串字面量可以包含以下特殊字符: 字符串字面量可以包含以下特殊字符:
*移特殊字符 `\0` (空字符)、`\\`(反斜线)、`\t` (水平制表符)、`\n` (换行符)、`\r` (回车符)、`\"` (双引号)、`\'` (单引号)。 *字符 `\0` (空字符)、`\\`(反斜线)、`\t` (水平制表符)、`\n` (换行符)、`\r` (回车符)、`\"` (双引号)、`\'` (单引号)。
* 单字节 Unicode 标量,写成 `\xnn`,其中 nn 为两位十六进制数。 * 单字节 Unicode 标量,写成 `\xnn`,其中 `nn` 为两位十六进制数。
* 双字节 Unicode 标量,写成 `\unnnn`,其中 nnnn 为四位十六进制数。 * 双字节 Unicode 标量,写成 `\unnnn`,其中 `nnnn` 为四位十六进制数。
* 四字节 Unicode 标量,写成 `\Unnnnnnnn`,其中 nnnnnnnn 为八位十六进制数。 * 四字节 Unicode 标量,写成 `\Unnnnnnnn`,其中 `nnnnnnnn` 为八位十六进制数。
下面的代码为各种特殊字符的使用示例。 下面的代码为各种特殊字符的使用示例。
`wiseWords` 常量包含了两个转移特殊字符 (双括号)
`wiseWords` 常量包含了两个转移特殊字符 (双括号)`dollarSign``blackHeart``sparklingHeart` 常量演示了三种不同格式的 Unicode 标量: `dollarSign``blackHeart``sparklingHeart` 常量演示了三种不同格式的 Unicode 标量:
``` ```
let wiseWords = "\"Imagination is more important than knowledge\" - Einstein" let wiseWords = "\"我是要成为海贼王的男人\" - 路飞"
// "Imagination is more important than knowledge" - Einstein // "我是要成为海贼王的男人" - 路飞
let dollarSign = "\x24" // $, Unicode scalar U+0024 let dollarSign = "\x24" // $, Unicode 标量 U+0024
let blackHeart = "\u2665" // ♥, Unicode scalar U+2665 let blackHeart = "\u2665" // ♥, Unicode 标量 U+2665
let sparklingHeart = "\U0001F496" // 💖, Unicode scalar U+1F496 let sparklingHeart = "\U0001F496" // 💖, Unicode 标量 U+1F496
``` ```
---
### 初始化空字符串 ### 初始化空字符串
为了构造一个很长的字符串,可以创建一个空字符串作为初始值。 为了构造一个很长的字符串,可以创建一个空字符串作为初始值。
可以将空的字符串字面量赋值给变量,也可以初始化一个新的 **String** 实例: 可以将空的字符串字面量赋值给变量,也可以初始化一个新的 **String** 实例:
``` ```
var emptyString = "" // empty string literal var emptyString = "" // 空字符串字面量
var anotherEmptyString = String() // initializer syntax var anotherEmptyString = String() // 初始化 String 实例
// 两个字符串为空,并且两者等价 // 两个字符串为空等价
``` ```
您可以通过检查其 **Boolean** 类型的 `isEmpty` 属性来判断该字符串是否为空: 您可以通过检查其 **Boolean** 类型的 `isEmpty` 属性来判断该字符串是否为空:
``` ```
if emptyString.isEmpty { if emptyString.isEmpty {
println("Nothing to see here") println("什么都没有")
} }
// 打印 "Nothing to see here" // 输出 "什么都没有"
``` ```
---
### 字符串可变性 ### 字符串可变性
您可以通过将一个特定字符串分配给一个变量来对其进行修改,或者分配给一个常量来保证其不会被修改: 您可以通过将一个特定字符串分配给一个变量来对其进行修改,或者分配给一个常量来保证其不会被修改:
@ -99,32 +108,37 @@ variableString += " and carriage"
// variableString 现在为 "Horse and carriage" // variableString 现在为 "Horse and carriage"
let constantString = "Highlander" let constantString = "Highlander"
constantString += " and another Highlander" constantString += " and another Highlander"
// 这会报告一个编译错误(compile-time error) - 常量不可以被修改。 // 这会报告一个编译错误 (compile-time error) - 常量不可以被修改。
``` ```
> 注意: > 注意:
> >
> 在 Objective-C 和 Cocoa 中,您通过选择两个不同的类( NSString 和 NSMutableString )来指定该字符串是否可以被修改Swift中的字符串是否可以修改仅通过定义的是变量还是常量来决定实现了多种类型可变性操作的统一。 > 在 Objective-C 和 Cocoa 中,您通过选择两个不同的类( `NSString``NSMutableString` )来指定该字符串是否可以被修改Swift 中的字符串是否可以修改仅通过定义的是变量还是常量来决定,实现了多种类型可变性操作的统一。
---
### 字符串是值类型 ### 字符串是值类型
Swift 的 **String** 类型是值类型。 Swift 的 **String** 类型是值类型。
如果您创建了一个新的字符串,那么当其进行常量、变量赋值操作或在函数/方法中传递时,会进行值拷贝。 如果您创建了一个新的字符串,那么当其进行常量、变量赋值操作或在函数/方法中传递时,会进行值拷贝。
任何情况下,都会对已有字符串值创建新副本,并对该新副本进行传递或赋值。 任何情况下,都会对已有字符串值创建新副本,并对该新副本进行传递或赋值操作
值类型在 [Structures and Enumerations Are Value Types](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ClassesAndStructures.html#//apple_ref/doc/uid/TP40014097-CH13-XID_104) 中进行了说明。 值类型在 [Structures and Enumerations Are Value Types](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ClassesAndStructures.html#//apple_ref/doc/uid/TP40014097-CH13-XID_104) 中进行了说明。
> 注意: > 注意:
> >
> 与 Cocoa 中的 NSString 不同,当您在 Cocoa 中创建了一个 NSString 实例,并将其传递给一个函数/方法,或者赋值给一个变量,您永远都是传递或赋值同一个 NSString 实例的一个引用,除非您特别要求进行值拷贝,否则字符串不会进行赋值新副本操作。 > 与 Cocoa 中的 NSString 不同,当您在 Cocoa 中创建了一个 NSString 实例,并将其传递给一个函数/方法,或者赋值给一个变量,您传递或赋值的是该 NSString 实例的一个引用,除非您特别要求进行值拷贝,否则字符串不会生成新的副本来进行赋值操作。
Swift 默认字符串拷贝的方式保证了在函数/方法中传递的是字符串的值,其明确了无论该值来自于哪里,都是您独自拥有的 Swift 默认字符串拷贝的方式保证了在函数/方法中传递的是字符串的值。
很明显无论该值来自于哪里,都是您独自拥有的。
您可以放心您传递的字符串本身不会被更改。 您可以放心您传递的字符串本身不会被更改。
在实际编译时Swift编译器会优化字符串的使用使实际的复制只发生在绝对必要的情况下这意味着您始终可以将字符串作为值类型的同时获得极高的性能。 在实际编译时Swift 编译器会优化字符串的使用,使实际的复制只发生在绝对必要的情况下,这意味着您将字符串作为值类型的同时可以获得极高的性能。
#### 使用字符(Characters) ---
Swift 的 **String** 类型表示特定序列的字符值的集合。 ### 使用字符(Characters)
Swift 的 **String** 类型表示特定序列的 **Character** (字符) 类型值的集合。
每一个字符值代表一个 Unicode 字符。 每一个字符值代表一个 Unicode 字符。
您可利用 for-in 循环来遍历字符串中的每一个字符: 您可利用 for-in 循环来遍历字符串中的每一个字符:
@ -147,9 +161,11 @@ for-in 循环在[For Loops](https://developer.apple.com/library/prerelease/ios/d
let yenSign: Character = "¥" let yenSign: Character = "¥"
``` ```
---
### 计算字符数量 ### 计算字符数量
通过调用全局 `countElements` 函数并将字符串作为参数进行传递可以获取该字符串的字符数量。 通过调用全局 `countElements` 函数并将字符串作为参数进行传递可以获取该字符串的字符数量。
``` ```
let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪" let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪"
@ -168,9 +184,11 @@ println("unusualMenagerie has \(countElements(unusualMenagerie)) characters")
> NSString 的 `length` 属性是基于利用 UTF-16 表示的十六位代码单元数字,而不是基于 Unicode 字符。 > NSString 的 `length` 属性是基于利用 UTF-16 表示的十六位代码单元数字,而不是基于 Unicode 字符。
> 为了解决这个问题NSString 的 `length` 属性在被 Swift的 **String** 访问时会成为 `utf16count`。 > 为了解决这个问题NSString 的 `length` 属性在被 Swift的 **String** 访问时会成为 `utf16count`。
---
### 连接字符串和字符 ### 连接字符串和字符
字符串和字符的值可以通过加法运算符 (+) 相加在一起并创建一个新的字符串值: 字符串和字符的值可以通过加法运算符 (`+`) 相加在一起并创建一个新的字符串值:
``` ```
let string1 = "hello" let string1 = "hello"
@ -200,15 +218,17 @@ welcome += character1
> >
>您不能将一个字符串或者字符添加到一个已经存在的字符变量上,因为字符变量只能包含一个字符。 >您不能将一个字符串或者字符添加到一个已经存在的字符变量上,因为字符变量只能包含一个字符。
---
### 字符串插值 ### 字符串插值
字符串插值是一种全新的构建字符串的方式,可以在其中包含常量、变量、字面量和表达式。 字符串插值是一种构建字符串的方式,可以在其中包含常量、变量、字面量和表达式。
您插入的字符串字面量的每一项都被包裹在以反斜线为前缀的圆括号中: 您插入的字符串字面量的每一项都被包裹在以反斜线为前缀的圆括号中:
``` ```
let multiplier = 3 let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)" let message = "\(multiplier) 乘以 2.5 \(Double(multiplier) * 2.5)"
// message is "3 times 2.5 is 7.5" // message is "3 乘以 2.5 7.5"
``` ```
在上面的例子中,`multiplier` 作为 `\(multiplier)` 被插入到一个字符串字面量中。 在上面的例子中,`multiplier` 作为 `\(multiplier)` 被插入到一个字符串字面量中。
@ -220,7 +240,9 @@ let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
>注意: >注意:
> >
>您插值字符串中写在括号中的表达式不能包含非转义双引号 (") 和反斜杠 (\\),并且不能包含回车或换行符。 >您插值字符串中写在括号中的表达式不能包含非转义双引号 (`"`) 和反斜杠 (`\`),并且不能包含回车或换行符。
---
### 比较字符串 ### 比较字符串
@ -231,12 +253,12 @@ Swift 提供了三种方式来比较字符串的值:字符串相等,前缀
如果两个字符串以同一顺序包含完全相同的字符,则认为两者字符串相等: 如果两个字符串以同一顺序包含完全相同的字符,则认为两者字符串相等:
``` ```
let quotation = "We're a lot alike, you and I." let quotation = "我们是一样一样滴."
let sameQuotation = "We're a lot alike, you and I." let sameQuotation = "我们是一样一样滴."
if quotation == sameQuotation { if quotation == sameQuotation {
println("These two strings are considered equal") println("这两个字符串被认为是相同的")
} }
// prints "These two strings are considered equal" // prints "这两个字符串被认为是相同的"
``` ```
##### 前缀/后缀相等 ##### 前缀/后缀相等
@ -278,7 +300,7 @@ println("There are \(act1SceneCount) scenes in Act 1")
##### 大写和小写字符串 ##### 大写和小写字符串
您可以通过字符串的 `uppercaseString``lowercaseString` 属性来访问一个字符串的大写/小写版本。 您可以通过字符串的 `uppercaseString``lowercaseString` 属性来访问大写/小写版本的字符串
``` ```
let normal = "Could you help me, please?" let normal = "Could you help me, please?"
@ -288,12 +310,14 @@ let whispered = normal.lowercaseString
// whispered 值为 "could you help me, please?" // whispered 值为 "could you help me, please?"
``` ```
---
### Unicode ### Unicode
Unicode 是文本编码和表示的国际标准 Unicode 是一个国际标准,用于文本编码和表示。
它使您可以用标准格式表示来自任意语言几乎所有的字符,并能够对文本文件或网页这样的外部资源中的字符进行读写操作。 它使您可以用标准格式表示来自任意语言几乎所有的字符,并能够对文本文件或网页这样的外部资源中的字符进行读写操作。
Swift 的字符串和字符类型是完全兼容 Unicode 的,它支持如下所述的一系列不同的 Unicode 编码。 Swift 的字符串和字符类型是完全兼容 Unicode 标准的,它支持如下所述的一系列不同的 Unicode 编码。
###### Unicode 术语(Terminology) ###### Unicode 术语(Terminology)
@ -315,7 +339,7 @@ Swift 提供了几种不同的方式来访问字符串的 Unicode 表示。
* UTF-16 代码单元集合 (利用字符串的 `utf16` 属性进行访问) * UTF-16 代码单元集合 (利用字符串的 `utf16` 属性进行访问)
* 21位的 Unicode 标量值集合 (利用字符串的 `unicodeScalars` 属性进行访问) * 21位的 Unicode 标量值集合 (利用字符串的 `unicodeScalars` 属性进行访问)
下面由 `D` `o` `g` `!``🐶` (狗脸表情Unicode 标量为 `U+1F436`)组成的字符串中的每一个字符代表着一种不同的表示: 下面由 `D` `o` `g` `!``🐶` (`DOG FACE`Unicode 标量为 `U+1F436`)组成的字符串中的每一个字符代表着一种不同的表示:
``` ```
let dogString = "Dog!🐶" let dogString = "Dog!🐶"
@ -324,7 +348,7 @@ let dogString = "Dog!🐶"
##### UTF-8 ##### UTF-8
您可以通过遍历字符串的 `utf8` 属性来访问它的 `UTF-8` 表示。 您可以通过遍历字符串的 `utf8` 属性来访问它的 `UTF-8` 表示。
其为 **UTF8View** 类型的属性,**UTF8View** 是无符号8位 (`UInt8`) 值的集合,每一个 `UIn8` 都是一个字符的 UTF-8 表示: 其为 **UTF8View** 类型的属性,**UTF8View** 是无符号8位 (`UInt8`) 值的集合,每一个 `UInt8` 都是一个字符的 UTF-8 表示:
``` ```
for codeUnit in dogString.utf8 { for codeUnit in dogString.utf8 {
@ -335,7 +359,7 @@ print("\n")
``` ```
上面的例子中前四个10进制代码单元值 (68, 111, 103, 33) 代表了字符 `D` `o` `g``!` ,他们的 UTF-8 表示与 ASCII 表示相同。 上面的例子中前四个10进制代码单元值 (68, 111, 103, 33) 代表了字符 `D` `o` `g``!` ,他们的 UTF-8 表示与 ASCII 表示相同。
后四个代码单元值 (240, 159, 144, 182) 是 `狗脸表情` 的4位 UTF-8 表示。 后四个代码单元值 (240, 159, 144, 182) 是 `DOG FACE` 的4位 UTF-8 表示。
##### UTF-16 ##### UTF-16
@ -352,7 +376,7 @@ print("\n")
同样,前四个代码单元值 (68, 111, 103, 33) 代表了字符 `D` `o` `g``!` ,他们的 UTF-16 代码单元和 UTF-8 完全相同。 同样,前四个代码单元值 (68, 111, 103, 33) 代表了字符 `D` `o` `g``!` ,他们的 UTF-16 代码单元和 UTF-8 完全相同。
第五和第六个代码单元值 (55357 and 56374) 是 `狗脸表情` 字符的UTF-16 表示。 第五和第六个代码单元值 (55357 and 56374) 是 `DOG FACE` 字符的UTF-16 表示。
第一个值为 `U+D83D` (十进制值为 55357),第二个值为 `U+DC36` (十进制值为 56374)。 第一个值为 `U+D83D` (十进制值为 55357),第二个值为 `U+DC36` (十进制值为 56374)。
##### Unicode 标量 (Scalars) ##### Unicode 标量 (Scalars)
@ -373,7 +397,7 @@ print("\n")
同样,前四个代码单元值 (68, 111, 103, 33) 代表了字符 `D` `o` `g``!` 同样,前四个代码单元值 (68, 111, 103, 33) 代表了字符 `D` `o` `g``!`
第五位数值128054是一个十六进制1F436的十进制表示。 第五位数值128054是一个十六进制1F436的十进制表示。
其等同于 `狗脸表情` 的Unicode 标量 U+1F436。 其等同于 `DOG FACE` 的Unicode 标量 U+1F436。
作为查询字符值属性的一种替代方法,每个 `UnicodeScalar` 值也可以用来构建一个新的字符串值,比如在字符串插值中使用: 作为查询字符值属性的一种替代方法,每个 `UnicodeScalar` 值也可以用来构建一个新的字符串值,比如在字符串插值中使用: