Fix some error and typo. (#705)
* Fix chess board size. Fix chess board size. * Fix quotation marks. Fix quotation marks. * Fix code error. Fix code error. * Update punctuation. Update punctuation. * Remove wrong punctuation. Remove wrong punctuation.
This commit is contained in:
@ -70,7 +70,7 @@ struct Fahrenheit {
|
|||||||
}
|
}
|
||||||
var f = Fahrenheit()
|
var f = Fahrenheit()
|
||||||
print("The default temperature is \(f.temperature)° Fahrenheit")
|
print("The default temperature is \(f.temperature)° Fahrenheit")
|
||||||
// 打印 "The default temperature is 32.0° Fahrenheit”
|
// 打印 "The default temperature is 32.0° Fahrenheit"
|
||||||
```
|
```
|
||||||
|
|
||||||
这个结构体定义了一个不带参数的构造器`init`,并在里面将存储型属性`temperature`的值初始化为`32.0`(华氏温度下水的冰点)。
|
这个结构体定义了一个不带参数的构造器`init`,并在里面将存储型属性`temperature`的值初始化为`32.0`(华氏温度下水的冰点)。
|
||||||
@ -602,7 +602,7 @@ class Food {
|
|||||||
|
|
||||||
```swift
|
```swift
|
||||||
let namedMeat = Food(name: "Bacon")
|
let namedMeat = Food(name: "Bacon")
|
||||||
// namedMeat 的名字是 "Bacon”
|
// namedMeat 的名字是 "Bacon"
|
||||||
```
|
```
|
||||||
|
|
||||||
`Food`类中的构造器`init(name: String)`被定义为一个指定构造器,因为它能确保`Food`实例的所有存储型属性都被初始化。`Food`类没有父类,所以`init(name: String)`构造器不需要调用`super.init()`来完成构造过程。
|
`Food`类中的构造器`init(name: String)`被定义为一个指定构造器,因为它能确保`Food`实例的所有存储型属性都被初始化。`Food`类没有父类,所以`init(name: String)`构造器不需要调用`super.init()`来完成构造过程。
|
||||||
@ -875,7 +875,7 @@ class CartItem: Product {
|
|||||||
if let twoSocks = CartItem(name: "sock", quantity: 2) {
|
if let twoSocks = CartItem(name: "sock", quantity: 2) {
|
||||||
print("Item: \(twoSocks.name), quantity: \(twoSocks.quantity)")
|
print("Item: \(twoSocks.name), quantity: \(twoSocks.quantity)")
|
||||||
}
|
}
|
||||||
// 打印 "Item: sock, quantity: 2”
|
// 打印 "Item: sock, quantity: 2"
|
||||||
```
|
```
|
||||||
|
|
||||||
倘若你以一个值为 0 的 `quantity` 来创建一个 `CartItem` 实例,那么将导致 `CartItem` 构造器失败:
|
倘若你以一个值为 0 的 `quantity` 来创建一个 `CartItem` 实例,那么将导致 `CartItem` 构造器失败:
|
||||||
@ -886,7 +886,7 @@ if let zeroShirts = CartItem(name: "shirt", quantity: 0) {
|
|||||||
} else {
|
} else {
|
||||||
print("Unable to initialize zero shirts")
|
print("Unable to initialize zero shirts")
|
||||||
}
|
}
|
||||||
// 打印 "Unable to initialize zero shirts”
|
// 打印 "Unable to initialize zero shirts"
|
||||||
```
|
```
|
||||||
|
|
||||||
同样地,如果你尝试传入一个值为空字符串的 `name`来创建一个 `CartItem` 实例,那么将导致父类 `Product` 的构造过程失败:
|
同样地,如果你尝试传入一个值为空字符串的 `name`来创建一个 `CartItem` 实例,那么将导致父类 `Product` 的构造过程失败:
|
||||||
@ -897,7 +897,7 @@ if let oneUnnamed = CartItem(name: "", quantity: 1) {
|
|||||||
} else {
|
} else {
|
||||||
print("Unable to initialize one unnamed product")
|
print("Unable to initialize one unnamed product")
|
||||||
}
|
}
|
||||||
// 打印 "Unable to initialize one unnamed product”
|
// 打印 "Unable to initialize one unnamed product"
|
||||||
```
|
```
|
||||||
|
|
||||||
<a name="overriding_a_failable_initializer"></a>
|
<a name="overriding_a_failable_initializer"></a>
|
||||||
@ -1019,7 +1019,7 @@ class SomeClass {
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
西洋跳棋游戏在一副黑白格交替的`10x10`的棋盘中进行。为了呈现这副游戏棋盘,`Checkerboard`结构体定义了一个属性`boardColors`,它是一个包含`100`个`Bool`值的数组。在数组中,值为`true`的元素表示一个黑格,值为`false`的元素表示一个白格。数组中第一个元素代表棋盘上左上角的格子,最后一个元素代表棋盘上右下角的格子。
|
西洋跳棋游戏在一副黑白格交替的 8 x 8 的棋盘中进行。为了呈现这副游戏棋盘,`Checkerboard`结构体定义了一个属性`boardColors`,它是一个包含`100`个`Bool`值的数组。在数组中,值为`true`的元素表示一个黑格,值为`false`的元素表示一个白格。数组中第一个元素代表棋盘上左上角的格子,最后一个元素代表棋盘上右下角的格子。
|
||||||
|
|
||||||
`boardColor`数组是通过一个闭包来初始化并设置颜色值的:
|
`boardColor`数组是通过一个闭包来初始化并设置颜色值的:
|
||||||
|
|
||||||
|
|||||||
@ -77,10 +77,10 @@ var reference3: Person?
|
|||||||
|
|
||||||
```swift
|
```swift
|
||||||
reference1 = Person(name: "John Appleseed")
|
reference1 = Person(name: "John Appleseed")
|
||||||
// 打印 "John Appleseed is being initialized”
|
// 打印 "John Appleseed is being initialized"
|
||||||
```
|
```
|
||||||
|
|
||||||
应当注意到当你调用`Person`类的构造函数的时候,`“John Appleseed is being initialized”`会被打印出来。由此可以确定构造函数被执行。
|
应当注意到当你调用`Person`类的构造函数的时候,`"John Appleseed is being initialized"`会被打印出来。由此可以确定构造函数被执行。
|
||||||
|
|
||||||
由于`Person`类的新实例被赋值给了`reference1`变量,所以`reference1`到`Person`类的新实例之间建立了一个强引用。正是因为这一个强引用,ARC 会保证`Person`实例被保持在内存中不被销毁。
|
由于`Person`类的新实例被赋值给了`reference1`变量,所以`reference1`到`Person`类的新实例之间建立了一个强引用。正是因为这一个强引用,ARC 会保证`Person`实例被保持在内存中不被销毁。
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ reference2 = nil
|
|||||||
|
|
||||||
```swift
|
```swift
|
||||||
reference3 = nil
|
reference3 = nil
|
||||||
// 打印 “John Appleseed is being deinitialized”
|
// 打印 "John Appleseed is being deinitialized"
|
||||||
```
|
```
|
||||||
|
|
||||||
<a name="strong_reference_cycles_between_class_instances"></a>
|
<a name="strong_reference_cycles_between_class_instances"></a>
|
||||||
@ -248,7 +248,7 @@ unit4A!.tenant = john
|
|||||||
|
|
||||||
```swift
|
```swift
|
||||||
john = nil
|
john = nil
|
||||||
// 打印 “John Appleseed is being deinitialized”
|
// 打印 "John Appleseed is being deinitialized"
|
||||||
```
|
```
|
||||||
|
|
||||||
唯一剩下的指向`Apartment`实例的强引用来自于变量`unit4A`。如果你断开这个强引用,再也没有指向`Apartment`实例的强引用了:
|
唯一剩下的指向`Apartment`实例的强引用来自于变量`unit4A`。如果你断开这个强引用,再也没有指向`Apartment`实例的强引用了:
|
||||||
@ -259,7 +259,7 @@ john = nil
|
|||||||
|
|
||||||
```swift
|
```swift
|
||||||
unit4A = nil
|
unit4A = nil
|
||||||
// 打印 “Apartment 4A is being deinitialized”
|
// 打印 "Apartment 4A is being deinitialized"
|
||||||
```
|
```
|
||||||
|
|
||||||
上面的两段代码展示了变量`john`和`unit4A`在被赋值为`nil`后,`Person`实例和`Apartment`实例的析构函数都打印出“销毁”的信息。这证明了引用循环被打破了。
|
上面的两段代码展示了变量`john`和`unit4A`在被赋值为`nil`后,`Person`实例和`Apartment`实例的析构函数都打印出“销毁”的信息。这证明了引用循环被打破了。
|
||||||
@ -339,8 +339,8 @@ john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
|
|||||||
|
|
||||||
```swift
|
```swift
|
||||||
john = nil
|
john = nil
|
||||||
// 打印 “John Appleseed is being deinitialized”
|
// 打印 "John Appleseed is being deinitialized"
|
||||||
// 打印 ”Card #1234567890123456 is being deinitialized”
|
// 打印 "Card #1234567890123456 is being deinitialized"
|
||||||
```
|
```
|
||||||
|
|
||||||
最后的代码展示了在`john`变量被设为`nil`后`Customer`实例和`CreditCard`实例的构造函数都打印出了“销毁”的信息。
|
最后的代码展示了在`john`变量被设为`nil`后`Customer`实例和`CreditCard`实例的构造函数都打印出了“销毁”的信息。
|
||||||
@ -397,7 +397,7 @@ class City {
|
|||||||
```swift
|
```swift
|
||||||
var country = Country(name: "Canada", capitalName: "Ottawa")
|
var country = Country(name: "Canada", capitalName: "Ottawa")
|
||||||
print("\(country.name)'s capital city is called \(country.capitalCity.name)")
|
print("\(country.name)'s capital city is called \(country.capitalCity.name)")
|
||||||
// 打印 “Canada's capital city is called Ottawa”
|
// 打印 "Canada's capital city is called Ottawa"
|
||||||
```
|
```
|
||||||
|
|
||||||
在上面的例子中,使用隐式解析可选值意味着满足了类的构造函数的两个构造阶段的要求。`capitalCity`属性在初始化完成后,能像非可选值一样使用和存取,同时还避免了循环强引用。
|
在上面的例子中,使用隐式解析可选值意味着满足了类的构造函数的两个构造阶段的要求。`capitalCity`属性在初始化完成后,能像非可选值一样使用和存取,同时还避免了循环强引用。
|
||||||
@ -441,11 +441,11 @@ class HTMLElement {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
`HTMLElement`类定义了一个`name`属性来表示这个元素的名称,例如代表头部元素的`"h1"`,代表段落的`“p”`,或者代表换行的`“br”`。`HTMLElement`还定义了一个可选属性`text`,用来设置 HTML 元素呈现的文本。
|
`HTMLElement`类定义了一个`name`属性来表示这个元素的名称,例如代表头部元素的`"h1"`,代表段落的`"p"`,或者代表换行的`"br"`。`HTMLElement`还定义了一个可选属性`text`,用来设置 HTML 元素呈现的文本。
|
||||||
|
|
||||||
除了上面的两个属性,`HTMLElement`还定义了一个`lazy`属性`asHTML`。这个属性引用了一个将`name`和`text`组合成 HTML 字符串片段的闭包。该属性是`Void -> String`类型,或者可以理解为“一个没有参数,返回`String`的函数”。
|
除了上面的两个属性,`HTMLElement`还定义了一个`lazy`属性`asHTML`。这个属性引用了一个将`name`和`text`组合成 HTML 字符串片段的闭包。该属性是`Void -> String`类型,或者可以理解为“一个没有参数,返回`String`的函数”。
|
||||||
|
|
||||||
默认情况下,闭包赋值给了`asHTML`属性,这个闭包返回一个代表 HTML 标签的字符串。如果`text`值存在,该标签就包含可选值`text`;如果`text`不存在,该标签就不包含文本。对于段落元素,根据`text`是`“some text”`还是`nil`,闭包会返回`"<p>some text</p>"`或者`"<p />"`。
|
默认情况下,闭包赋值给了`asHTML`属性,这个闭包返回一个代表 HTML 标签的字符串。如果`text`值存在,该标签就包含可选值`text`;如果`text`不存在,该标签就不包含文本。对于段落元素,根据`text`是`"some text"`还是`nil`,闭包会返回`"<p>some text</p>"`或者`"<p />"`。
|
||||||
|
|
||||||
可以像实例方法那样去命名、使用`asHTML`属性。然而,由于`asHTML`是闭包而不是实例方法,如果你想改变特定 HTML 元素的处理方式的话,可以用自定义的闭包来取代默认值。
|
可以像实例方法那样去命名、使用`asHTML`属性。然而,由于`asHTML`是闭包而不是实例方法,如果你想改变特定 HTML 元素的处理方式的话,可以用自定义的闭包来取代默认值。
|
||||||
|
|
||||||
@ -458,7 +458,7 @@ heading.asHTML = {
|
|||||||
return "<\(heading.name)>\(heading.text ?? defaultText)</\(heading.name)>"
|
return "<\(heading.name)>\(heading.text ?? defaultText)</\(heading.name)>"
|
||||||
}
|
}
|
||||||
print(heading.asHTML())
|
print(heading.asHTML())
|
||||||
// 打印 “<h1>some default text</h1>”
|
// 打印 "<h1>some default text</h1>"
|
||||||
```
|
```
|
||||||
|
|
||||||
> 注意
|
> 注意
|
||||||
@ -471,7 +471,7 @@ print(heading.asHTML())
|
|||||||
```swift
|
```swift
|
||||||
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
|
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
|
||||||
print(paragraph!.asHTML())
|
print(paragraph!.asHTML())
|
||||||
// 打印 “<p>hello, world</p>”
|
// 打印 "<p>hello, world</p>"
|
||||||
```
|
```
|
||||||
|
|
||||||
> 注意
|
> 注意
|
||||||
@ -571,7 +571,7 @@ class HTMLElement {
|
|||||||
```swift
|
```swift
|
||||||
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
|
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
|
||||||
print(paragraph!.asHTML())
|
print(paragraph!.asHTML())
|
||||||
// 打印 “<p>hello, world</p>”
|
// 打印 "<p>hello, world</p>"
|
||||||
```
|
```
|
||||||
|
|
||||||
使用捕获列表后引用关系如下图所示:
|
使用捕获列表后引用关系如下图所示:
|
||||||
@ -582,7 +582,7 @@ print(paragraph!.asHTML())
|
|||||||
|
|
||||||
```swift
|
```swift
|
||||||
paragraph = nil
|
paragraph = nil
|
||||||
// 打印 “p is being deinitialized”
|
// 打印 "p is being deinitialized"
|
||||||
```
|
```
|
||||||
|
|
||||||
你可以查看[捕获列表](../chapter3/04_Expressions.html)章节,获取更多关于捕获列表的信息。
|
你可以查看[捕获列表](../chapter3/04_Expressions.html)章节,获取更多关于捕获列表的信息。
|
||||||
|
|||||||
@ -96,15 +96,15 @@ class VendingMachine {
|
|||||||
|
|
||||||
func vend(itemNamed name: String) throws {
|
func vend(itemNamed name: String) throws {
|
||||||
guard let item = inventory[name] else {
|
guard let item = inventory[name] else {
|
||||||
throw VendingMachineError.InvalidSelection
|
throw VendingMachineError.invalidSelection
|
||||||
}
|
}
|
||||||
|
|
||||||
guard item.count > 0 else {
|
guard item.count > 0 else {
|
||||||
throw VendingMachineError.OutOfStock
|
throw VendingMachineError.outOfStock
|
||||||
}
|
}
|
||||||
|
|
||||||
guard item.price <= coinsDeposited else {
|
guard item.price <= coinsDeposited else {
|
||||||
throw VendingMachineError.InsufficientFunds(coinsNeeded: item.price - coinsDeposited)
|
throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - coinsDeposited)
|
||||||
}
|
}
|
||||||
|
|
||||||
coinsDeposited -= item.price
|
coinsDeposited -= item.price
|
||||||
@ -136,7 +136,7 @@ func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {
|
|||||||
|
|
||||||
上例中,`buyFavoriteSnack(person:vendingMachine:) `函数会查找某人最喜欢的零食,并通过调用`vend(itemNamed:)`方法来尝试为他们购买。因为`vend(itemNamed:)`方法能抛出错误,所以在调用的它时候在它前面加了`try`关键字。
|
上例中,`buyFavoriteSnack(person:vendingMachine:) `函数会查找某人最喜欢的零食,并通过调用`vend(itemNamed:)`方法来尝试为他们购买。因为`vend(itemNamed:)`方法能抛出错误,所以在调用的它时候在它前面加了`try`关键字。
|
||||||
|
|
||||||
`throwing`构造器能像`throwing`函数一样传递错误.例如下面代码中的`PurchasedSnack`构造器在构造过程中调用了throwing函数,并且通过传递到它的调用者来处理这些错误。
|
`throwing`构造器能像`throwing`函数一样传递错误。例如下面代码中的`PurchasedSnack`构造器在构造过程中调用了throwing函数,并且通过传递到它的调用者来处理这些错误。
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
struct PurchasedSnack {
|
struct PurchasedSnack {
|
||||||
@ -175,11 +175,11 @@ var vendingMachine = VendingMachine()
|
|||||||
vendingMachine.coinsDeposited = 8
|
vendingMachine.coinsDeposited = 8
|
||||||
do {
|
do {
|
||||||
try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine)
|
try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine)
|
||||||
} catch VendingMachineError.InvalidSelection {
|
} catch VendingMachineError.invalidSelection {
|
||||||
print("Invalid Selection.")
|
print("Invalid Selection.")
|
||||||
} catch VendingMachineError.OutOfStock {
|
} catch VendingMachineError.outOfStock {
|
||||||
print("Out of Stock.")
|
print("Out of Stock.")
|
||||||
} catch VendingMachineError.InsufficientFunds(let coinsNeeded) {
|
} catch VendingMachineError.insufficientFunds(let coinsNeeded) {
|
||||||
print("Insufficient funds. Please insert an additional \(coinsNeeded) coins.")
|
print("Insufficient funds. Please insert an additional \(coinsNeeded) coins.")
|
||||||
}
|
}
|
||||||
// 打印 “Insufficient funds. Please insert an additional 2 coins.”
|
// 打印 “Insufficient funds. Please insert an additional 2 coins.”
|
||||||
@ -189,7 +189,7 @@ do {
|
|||||||
|
|
||||||
### 将错误转换成可选值
|
### 将错误转换成可选值
|
||||||
|
|
||||||
可以使用`try?`通过将错误转换成一个可选值来处理错误。如果在评估`try?`表达式时一个错误被抛出,那么表达式的值就是`nil`。例如,在下面的代码中,`x`和`y`有着相同的数值和等价的含义:
|
可以使用`try?`通过将错误转换成一个可选值来处理错误。如果在评估`try?`表达式时一个错误被抛出,那么表达式的值就是`nil`。例如,在下面的代码中,`x`和`y`有着相同的数值和等价的含义:
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
func someThrowingFunction() throws -> Int {
|
func someThrowingFunction() throws -> Int {
|
||||||
@ -208,7 +208,7 @@ do {
|
|||||||
|
|
||||||
如果`someThrowingFunction()`抛出一个错误,`x`和`y`的值是`nil`。否则`x`和`y`的值就是该函数的返回值。注意,无论`someThrowingFunction()`的返回值类型是什么类型,`x`和`y`都是这个类型的可选类型。例子中此函数返回一个整型,所以`x`和`y`是可选整型。
|
如果`someThrowingFunction()`抛出一个错误,`x`和`y`的值是`nil`。否则`x`和`y`的值就是该函数的返回值。注意,无论`someThrowingFunction()`的返回值类型是什么类型,`x`和`y`都是这个类型的可选类型。例子中此函数返回一个整型,所以`x`和`y`是可选整型。
|
||||||
|
|
||||||
如果你想对所有的错误都采用同样的方式来处理,用`try?`就可以让你写出简洁的错误处理代码。例如,下面的代码用几种方式来获取数据,如果所有方式都失败了则返回`nil`:
|
如果你想对所有的错误都采用同样的方式来处理,用`try?`就可以让你写出简洁的错误处理代码。例如,下面的代码用几种方式来获取数据,如果所有方式都失败了则返回`nil`。
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
func fetchData() -> Data? {
|
func fetchData() -> Data? {
|
||||||
@ -222,7 +222,7 @@ func fetchData() -> Data? {
|
|||||||
|
|
||||||
有时你知道某个`throwing`函数实际上在运行时是不会抛出错误的,在这种情况下,你可以在表达式前面写`try!`来禁用错误传递,这会把调用包装在一个不会有错误抛出的运行时断言中。如果真的抛出了错误,你会得到一个运行时错误。
|
有时你知道某个`throwing`函数实际上在运行时是不会抛出错误的,在这种情况下,你可以在表达式前面写`try!`来禁用错误传递,这会把调用包装在一个不会有错误抛出的运行时断言中。如果真的抛出了错误,你会得到一个运行时错误。
|
||||||
|
|
||||||
例如,下面的代码使用了`loadImage(atPath:)`函数,该函数从给定的路径加载图片资源,如果图片无法载入则抛出一个错误。在这种情况下,因为图片是和应用绑定的,运行时不会有错误抛出,所以适合禁用错误传递:
|
例如,下面的代码使用了`loadImage(atPath:)`函数,该函数从给定的路径加载图片资源,如果图片无法载入则抛出一个错误。在这种情况下,因为图片是和应用绑定的,运行时不会有错误抛出,所以适合禁用错误传递。
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")
|
let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")
|
||||||
|
|||||||
@ -114,7 +114,7 @@ print("Media library contains \(movieCount) movies and \(songCount) songs")
|
|||||||
|
|
||||||
某类型的一个常量或变量可能在幕后实际上属于一个子类。当确定是这种情况时,你可以尝试向下转到它的子类型,用*类型转换操作符*(`as?` 或 `as!`)。
|
某类型的一个常量或变量可能在幕后实际上属于一个子类。当确定是这种情况时,你可以尝试向下转到它的子类型,用*类型转换操作符*(`as?` 或 `as!`)。
|
||||||
|
|
||||||
因为向下转型可能会失败,类型转型操作符带有两种不同形式。条件形式`as?` 返回一个你试图向下转成的类型的可选值。强制形式 `as!` 把试图向下转型和强制解包(转换结果结合为一个操作。
|
因为向下转型可能会失败,类型转型操作符带有两种不同形式。条件形式`as?` 返回一个你试图向下转成的类型的可选值。强制形式 `as!` 把试图向下转型和强制解包转换结果结合为一个操作。
|
||||||
|
|
||||||
当你不确定向下转型可以成功时,用类型转换的条件形式(`as?`)。条件形式的类型转换总是返回一个可选值,并且若下转是不可能的,可选值将是 `nil`。这使你能够检查向下转型是否成功。
|
当你不确定向下转型可以成功时,用类型转换的条件形式(`as?`)。条件形式的类型转换总是返回一个可选值,并且若下转是不可能的,可选值将是 `nil`。这使你能够检查向下转型是否成功。
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user