From 150626ec6b1e61aeaaa4516b026a6cbed54c1063 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=83=91=E4=B8=80=E4=B8=80?=
<43005999+YiYiZheng@users.noreply.github.com>
Date: Mon, 19 Nov 2018 01:22:44 +0800
Subject: [PATCH] Update 16_Optional_Chaining for Swift 4.2 (#828)
* Update 19 Nested types for Swift 4.2
* Revert "Update 19 Nested types for Swift 4.2"
This reverts commit 7e0fbe87ed370b36bd5134e19241e083e5ef8f4c.
* Update 16_Optional_Chaining
* Update 16_Optional_Chaining
* Update 16_Optional_Chaining
---
source/chapter2/16_Optional_Chaining.md | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/source/chapter2/16_Optional_Chaining.md b/source/chapter2/16_Optional_Chaining.md
index ff26362f..bc2540ec 100755
--- a/source/chapter2/16_Optional_Chaining.md
+++ b/source/chapter2/16_Optional_Chaining.md
@@ -13,7 +13,7 @@
为了反映可选链式调用可以在空值(`nil`)上调用的事实,不论这个调用的属性、方法及下标返回的值是不是可选值,它的返回结果都是一个可选值。你可以利用这个返回值来判断你的可选链式调用是否调用成功,如果调用有返回值则说明调用成功,返回 `nil` 则说明调用失败。
-特别地,可选链式调用的返回结果与原本的返回结果具有相同的类型,但是被包装成了一个可选值。例如,使用可选链式调用访问属性,当可选链式调用成功时,如果属性原本的返回结果是 `Int` 类型,则会变为 `Int?` 类型。
+这里需要特别指出,可选链式调用的返回结果与原本的返回结果具有相同的类型,但是被包装成了一个可选值。例如,使用可选链式调用访问属性,当可选链式调用成功时,如果属性原本的返回结果是 `Int` 类型,则会变为 `Int?` 类型。
下面几段代码将解释可选链式调用和强制展开的不同。
@@ -31,7 +31,7 @@ class Residence {
`Residence` 有一个 `Int` 类型的属性 `numberOfRooms`,其默认值为 `1`。`Person` 具有一个可选的 `residence` 属性,其类型为 `Residence?`。
-假如你创建了一个新的 `Person` 实例,它的 `residence` 属性由于是是可选型而将初始化为 `nil`,在下面的代码中,`john` 有一个值为 `nil` 的 `residence` 属性:
+假如你创建了一个新的 `Person` 实例,它的 `residence` 属性由于是是可选类型而将被初始化为 `nil`,在下面的代码中,`john` 有一个值为 `nil` 的 `residence` 属性:
```swift
let john = Person()
@@ -44,7 +44,7 @@ let roomCount = john.residence!.numberOfRooms
// 这会引发运行时错误
```
-`john.residence` 为非 `nil` 值的时候,上面的调用会成功,并且把 `roomCount` 设置为 `Int` 类型的房间数量。正如上面提到的,当 `residence` 为 `nil` 的时候上面这段代码会触发运行时错误。
+`john.residence` 为非 `nil` 值的时候,上面的调用会成功,并且把 `roomCount` 设置为 `Int` 类型的房间数量。正如上面提到的,当 `residence` 为 `nil` 的时候,上面这段代码会触发运行时错误。
可选链式调用提供了另一种访问 `numberOfRooms` 的方式,使用问号(`?`)来替代原来的叹号(`!`):
@@ -83,7 +83,7 @@ if let roomCount = john.residence?.numberOfRooms {
## 为可选链式调用定义模型类
-通过使用可选链式调用可以调用多层属性、方法和下标。这样可以在复杂的模型中向下访问各种子属性,并且判断能否访问子属性的属性、方法或下标。
+通过使用可选链式调用可以调用多层属性、方法和下标。这样可以在复杂的模型中向下访问各种子属性,并且判断能否访问子属性的属性、方法和下标。
下面这段代码定义了四个模型类,这些例子包括多层可选链式调用。为了方便说明,在 `Person` 和 `Residence` 的基础上增加了 `Room` 类和 `Address` 类,以及相关的属性、方法以及下标。
@@ -135,7 +135,7 @@ class Room {
}
```
-最后一个类是 `Address`,这个类有三个 `String?` 类型的可选属性。`buildingName` 以及 `buildingNumber` 属性分别表示某个大厦的名称和号码,第三个属性 `street` 表示大厦所在街道的名称:
+最后一个类是 `Address`,这个类有三个 `String?` 类型的可选属性。`buildingName` 以及 `buildingNumber` 属性分别表示大厦的名称和号码,第三个属性 `street` 表示大厦所在街道的名称:
```swift
class Address {
@@ -145,7 +145,7 @@ class Address {
func buildingIdentifier() -> String? {
if buildingName != nil {
return buildingName
- } else if buildingNumber != nil && street != nil {
+ } else if let buildingNumber = buildingNumber, let street = street {
return "\(buildingNumber) \(street)"
} else {
return nil
@@ -154,14 +154,14 @@ class Address {
}
```
-`Address` 类提供了 `buildingIdentifier()` 方法,返回值为 `String?`。 如果 `buildingName` 有值则返回 `buildingName`。或者,如果 `buildingNumber` 和 `street` 均有值则返回 `buildingNumber`。否则,返回 `nil`。
+`Address` 类提供了 `buildingIdentifier()` 方法,返回值为 `String?`。 如果 `buildingName` 有值则返回 `buildingName`。或者,如果 `buildingNumber` 和 `street` 均有值,则返回两者拼接得到的字符串。否则,返回 `nil`。
## 通过可选链式调用访问属性
正如[使用可选链式调用代替强制展开](#optional_chaining_as_an_alternative_to_forced_unwrapping)中所述,可以通过可选链式调用在一个可选值上访问它的属性,并判断访问是否成功。
-下面的代码创建了一个 `Person` 实例,然后像之前一样,尝试访问 `numberOfRooms` 属性:
+使用前面定义过的类,创建一个 `Person` 实例,然后像之前一样,尝试访问 `numberOfRooms` 属性:
```swift
let john = Person()
@@ -186,7 +186,7 @@ john.residence?.address = someAddress
在这个例子中,通过 `john.residence` 来设定 `address` 属性也会失败,因为 `john.residence` 当前为 `nil`。
-上面代码中的赋值过程是可选链式调用的一部分,这意味着可选链式调用失败时,等号右侧的代码不会被执行。对于上面的代码来说,很难验证这一点,因为像这样赋值一个常量没有任何副作用。下面的代码完成了同样的事情,但是它使用一个函数来创建 `Address` 实例,然后将该实例返回用于赋值。该函数会在返回前打印“Function was called”,这使你能验证等号右侧的代码是否被执行。
+上面代码中的赋值过程是可选链式调用的一部分,这意味着可选链式调用失败时,等号右侧的代码不会被执行。对于上面的代码来说,很难验证这一点,因为像这样赋值一个常量没有任何副作用。下面的代码完成了同样的事情,但是它使用一个函数来创建 `Address` 实例,然后将该实例返回用于赋值。该函数会在返回前打印 “Function was called”,这使你能验证等号右侧的代码是否被执行。
```swift
func createAddress() -> Address {
@@ -299,7 +299,7 @@ testScores["Brian"]?[0] = 72
// "Dave" 数组现在是 [91, 82, 84],"Bev" 数组现在是 [80, 94, 81]
```
-上面的例子中定义了一个 `testScores` 数组,包含了两个键值对,把 `String` 类型的键映射到一个 `Int` 值的数组。这个例子用可选链式调用把 `"Dave"` 数组中第一个元素设为 `91`,把 `"Bev"` 数组的第一个元素 `+1`,然后尝试把 `"Brian"` 数组中的第一个元素设为 `72`。前两个调用成功,因为 `testScores` 字典中包含 `"Dave"` 和 `"Bev"` 这两个键。但是 `testScores` 字典中没有 `"Brian"` 这个键,所以第三个调用失败。
+上面的例子中定义了一个 `testScores` 数组,包含了两个键值对,分别把 `String` 类型的键映射到一个 `Int` 值的数组。这个例子用可选链式调用把 `"Dave"` 数组中第一个元素设为 `91`,把 `"Bev"` 数组的第一个元素 `+1`,然后尝试把 `"Brian"` 数组中的第一个元素设为 `72`。前两个调用成功,因为 `testScores` 字典中包含 `"Dave"` 和 `"Bev"` 这两个键。但是 `testScores` 字典中没有 `"Brian"` 这个键,所以第三个调用失败。
## 连接多层可选链式调用
@@ -367,6 +367,7 @@ if let buildingIdentifier = john.residence?.address?.buildingIdentifier() {
```swift
if let beginsWithThe =
+
john.residence?.address?.buildingIdentifier()?.hasPrefix("The") {
if beginsWithThe {
print("John's building identifier begins with \"The\".")