update chapter 'The Basics' to swift 3

This commit is contained in:
chenmingbiao
2016-09-17 16:21:59 +08:00
parent 498143e4f1
commit 6a9b24881e
2 changed files with 126 additions and 105 deletions

View File

@ -13,7 +13,12 @@
> 校对:[shanks](http://codebuild.me)[overtrue](https://github.com/overtrue)
>
> 2.2
> 校对:[SketchK](https://github.com/SketchK) 2016-05-11
> 校对:[SketchK](https://github.com/SketchK)
>
> 3.0
> 校对:[CMB](https://github.com/chenmingbiao)
>
> 版本日期2016-09-13
本页包含内容:
@ -45,7 +50,7 @@
- [错误处理](#error_handling)
- [断言](#assertions)
Swift 是一门开发 iOS, OS X 和 watchOS 应用的新语言。然而,如果你有 C 或者 Objective-C 开发经验的话,你会发现 Swift 的很多内容都是你熟悉的。
Swift 是一门开发 iOS, macOS, watchOS 和 tvOS 应用的新语言。然而,如果你有 C 或者 Objective-C 开发经验的话,你会发现 Swift 的很多内容都是你熟悉的。
Swift 包含了 C 和 Objective-C 上所有基础数据类型,`Int`表示整型值; `Double``Float` 表示浮点型值; `Bool` 是布尔型值;`String` 是文本型数据。 Swift 还提供了三个基本的集合类型,`Array` `Set``Dictionary` ,详见[集合类型](04_Collection_Types.html)。
@ -55,7 +60,7 @@ Swift 包含了 C 和 Objective-C 上所有基础数据类型,`Int`表示整
Swift 还增加了可选Optional类型用于处理值缺失的情况。可选表示 “那儿有一个值,并且它等于 x ” 或者 “那儿没有值” 。可选有点像在 Objective-C 中使用 `nil` ,但是它可以用在任何类型上,不仅仅是类。可选类型比 Objective-C 中的 `nil` 指针更加安全也更具表现力,它是 Swift 许多强大特性的重要组成部分。
Swift 是一门类型安全的语言可选类型就是一个很好的例子。Swift 可以让你清楚地知道值的类型。如果你的代码期望得到一个`String`,类型安全会阻止你不小心传入一个`Int`。你可以在开发阶段尽早发现并修正错误。
Swift 是一门类型安全的语言可选类型就是一个很好的例子。Swift 可以让你清楚地知道值的类型。如果你的代码期望得到一个 `String` ,类型安全会阻止你不小心传入一个 `Int` 。同样的,如果你的代码期望得到一个 `String`,类型安全会阻止你意外传入一个可选的 `String` 。你可以在开发阶段尽早发现并修正错误。
<a name="constants_and_variables"></a>
## 常量和变量
@ -85,7 +90,7 @@ var x = 0.0, y = 0.0, z = 0.0
```
> 注意:
如果你的代码中有不需要改变的值,请使用`let`关键字将它声明为常量。只将需要改变的值声明为变量。
> 如果你的代码中有不需要改变的值,请使用 `let` 关键字将它声明为常量。只将需要改变的值声明为变量。
<a name="type_annotations"></a>
### 类型标注
@ -117,7 +122,7 @@ var red, green, blue: Double
```
> 注意:
一般来说你很少需要写类型标注。如果你在声明常量或者变量的时候赋了一个初始值Swift可以推断出这个常量或者变量的类型请参考[类型安全和类型推断](#type_safety_and_type_inference)。在上面的例子中,没有给`welcomeMessage`赋初始值,所以变量`welcomeMessage`的类型是通过一个类型标注指定的,而不是通过初始值推断的。
> 一般来说你很少需要写类型标注。如果你在声明常量或者变量的时候赋了一个初始值Swift可以推断出这个常量或者变量的类型请参考[类型安全和类型推断](#type_safety_and_type_inference)。在上面的例子中,没有给 `welcomeMessage` 赋初始值,所以变量 `welcomeMessage` 的类型是通过一个类型标注指定的,而不是通过初始值推断的。
<a name="naming"></a>
### 常量和变量的命名
@ -135,7 +140,7 @@ let 🐶🐮 = "dogcow"
一旦你将常量或者变量声明为确定的类型,你就不能使用相同的名字再次进行声明,或者改变其存储的值的类型。同时,你也不能将常量与变量进行互转。
> 注意:
如果你需要使用与Swift保留关键字相同的名称作为常量或者变量名你可以使用反引号`)将关键字包围的方式将其作为名字使用。无论如何,你应当避免使用关键字作为常量或变量名,除非你别无选择。
> 如果你需要使用与Swift保留关键字相同的名称作为常量或者变量名你可以使用反引号`)将关键字包围的方式将其作为名字使用。无论如何,你应当避免使用关键字作为常量或变量名,除非你别无选择。
你可以更改现有的变量值为其他同类型的值,在下面的例子中,`friendlyWelcome`的值从`"Hello!"`改为了`"Bonjour!"`:
@ -227,6 +232,7 @@ Swift 提供了81632和64位的有符号和无符号整数类型。这些
let minValue = UInt8.min // minValue 为 0是 UInt8 类型
let maxValue = UInt8.max // maxValue 为 255是 UInt8 类型
```
`min``max` 所传回值的类型,正是其所对的整数类型(如上例UInt8, 所传回的类型是UInt8),可用在表达式中相同类型值旁。
<a name="Int"></a>
@ -261,7 +267,7 @@ Swift 也提供了一个特殊的无符号类型`UInt`,长度与当前平台
* `Float`表示32位浮点数。精度要求不高的话可以使用此类型。
> 注意:
`Double`精确度很高至少有15位数字而`Float`只有6位数字。选择哪个类型取决于你的代码需要处理的值的范围。
`Double`精确度很高至少有15位数字`Float`只有6位数字。选择哪个类型取决于你的代码需要处理的值的范围,在两种类型都匹配的情况下,将优先选择 `Double`
<a name="type_safety_and_type_inference"></a>
## 类型安全和类型推断
@ -323,10 +329,12 @@ let hexadecimalInteger = 0x11 // 十六进制的17
浮点字面量可以是十进制(没有前缀)或者是十六进制(前缀是 `0x` 。小数点两边必须有至少一个十进制数字或者是十六进制的数字。十进制浮点数也可以有一个可选的指数exponent),通过大写或者小写的 `e` 来指定;十六进制浮点数必须有一个指数,通过大写或者小写的 `p` 来指定。
如果一个十进制数的指数为 `exp`那这个数相当于基数和10^exp的乘积
* `1.25e2` 表示 1.25 × 10^2等于 `125.0`
* `1.25e-2` 表示 1.25 × 10^-2等于 `0.0125`
如果一个十六进制数的指数为`exp`那这个数相当于基数和2^exp的乘积
* `0xFp2` 表示 15 × 2^2等于 `60.0`
* `0xFp-2` 表示 15 × 2^-2等于 `3.75`
@ -547,7 +555,7 @@ print("The status message is \(http200Status.description)")
* 没有值
> 注意:
C 和 Objective-C 中并没有可选类型这个概念。最接近的是 Objective-C 中的一个特性,一个方法要不返回一个对象要不返回`nil``nil`表示“缺少一个合法的对象”。然而,这只对对象起作用——对于结构体,基本的 C 类型或者枚举类型不起作用。对于这些类型Objective-C 方法一般会返回一个特殊值(比如`NSNotFound`来暗示值缺失。这种方法假设方法的调用者知道并记得对特殊值进行判断。然而Swift 的可选类型可以让你暗示_任意类型_的值缺失,并不需要一个特殊值。
C 和 Objective-C 中并没有可选类型这个概念。最接近的是 Objective-C 中的一个特性,一个方法要不返回一个对象要不返回`nil``nil`表示“缺少一个合法的对象”。然而,这只对对象起作用——对于结构体,基本的 C 类型或者枚举类型不起作用。对于这些类型Objective-C 方法一般会返回一个特殊值(比如`NSNotFound`来暗示值缺失。这种方法假设方法的调用者知道并记得对特殊值进行判断。然而Swift 的可选类型可以让你暗示*任意类型*的值缺失,并不需要一个特殊值。
来看一个例子。Swift 的 `Int` 类型有一种构造器,作用是将一个 `String` 值转换成一个 `Int` 值。然而,并不是所有的字符串都可以转换成一个整数。字符串 `"123"` 可以被转换成数字 `123` ,但是字符串 `"hello, world"` 不行。
@ -559,7 +567,7 @@ let convertedNumber = Int(possibleNumber)
// convertedNumber 被推测为类型 "Int?" 或者类型 "optional Int"
```
因为该构造器可能会失败,所以它返回一个_可选类型_optional`Int`,而不是一个`Int`。一个可选的`Int`被写作`Int?`而不是`Int`。问号暗示包含的值是可选类型,也就是说可能包含`Int`值也可能*不包含值*。(不能包含其他任何值比如`Bool`值或者`String`值。只能是`Int`或者什么都没有。)
因为该构造器可能会失败,所以它返回一个*可选类型*optional`Int`,而不是一个 `Int`。一个可选的 `Int` 被写作 `Int?` 而不是 `Int`。问号暗示包含的值是可选类型,也就是说可能包含 `Int` 值也可能*不包含值*。(不能包含其他任何值比如 `Bool` 值或者 `String` 值。只能是 `Int` 或者什么都没有。)
<a name="nil"></a>
### nil
@ -591,7 +599,7 @@ Swift 的`nil`和 Objective-C 中的`nil`并不一样。在 Objective-C 中,`n
你可以使用 `if` 语句和 `nil` 比较来判断一个可选值是否包含值。你可以使用“相等”(`==`)或“不等”(`!=`)来执行比较。
如果可选类型有值,它将不等于`nil`:
如果可选类型有值,它将不等于 `nil`
```swift
if convertedNumber != nil {
@ -599,7 +607,8 @@ if convertedNumber != nil {
}
// 输出 "convertedNumber contains some integer value."
```
当你确定可选类型确实包含值之后,你可以在可选的名字后面加一个感叹号(`!`来获取值。这个惊叹号表示“我知道这个可选有值请使用它。”这被称为可选值的_强制解析forced unwrapping_
当你确定可选类型确实包含值之后,你可以在可选的名字后面加一个感叹号(`!`)来获取值。这个惊叹号表示“我知道这个可选有值,请使用它。”这被称为可选值的*强制解析forced unwrapping*
```swift
if convertedNumber != nil {
@ -641,19 +650,31 @@ if let actualNumber = Int(possibleNumber) {
“如果 `Int(possibleNumber)` 返回的可选 `Int` 包含一个值,创建一个叫做 `actualNumber` 的新常量并将可选包含的值赋给它。”
如果转换成功,`actualNumber`常量可以在`if`语句的第一个分支中使用。它已经被可选类型 _包含的_ 值初始化过,所以不需要再使用`!`后缀来获取它的值。在这个例子中,`actualNumber`只被用来输出转换结果。
如果转换成功,`actualNumber` 常量可以在 `if` 语句的第一个分支中使用。它已经被可选类型 *包含的* 值初始化过,所以不需要再使用 `!` 后缀来获取它的值。在这个例子中,`actualNumber` 只被用来输出转换结果。
你可以在可选绑定中使用常量和变量。如果你想在`if`语句的第一个分支中操作 `actualNumber` 的值,你可以改成 `if var actualNumber`,这样可选类型包含的值就会被赋给一个变量而非常量。
你可以包含多个可选绑定在`if`语句中,并使用`where`子句做布尔值判断。
你可以包含多个可选绑定或多个布尔条件在一个 `if` 语句中,只要使用逗号分开就行。如果所有可选绑定的值为 `nil` 或者所有布尔条件语句都为 `false`,这样整个 `if` 条件判断都是为 `false`,这时你就需要使用嵌套 `if` 条件语句来处理,如下所示:
```swift
if let firstNumber = Int("4"), secondNumber = Int("42") where firstNumber < secondNumber {
print("\(firstNumber) < \(secondNumber)")
if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber && secondNumber < 100 {
print("\(firstNumber) < \(secondNumber) < 100")
}
// prints "4 < 42"
// Prints "4 < 42 < 100"
if let firstNumber = Int("4") {
if let secondNumber = Int("42") {
if firstNumber < secondNumber && secondNumber < 100 {
print("\(firstNumber) < \(secondNumber) < 100")
}
}
}
// Prints "4 < 42 < 100"
```
> 注意:
> 在 `if` 条件语句中使用常量和变量来创建一个可选绑定,仅在 `if` 语句的句中(`body`)中才能获取到值。相反,在 `guard` 语句中使用常量和变量来创建一个可选绑定,仅在 `guard` 语句外且在语句后才能获取到值,请参考[控制流](./05_Control_Flow#early_exit.html)。
<a name="implicityly_unwrapped_optionals"></a>
### 隐式解析可选类型
@ -678,7 +699,7 @@ let implicitString: String = assumedString // 不需要感叹号
你可以把隐式解析可选类型当做一个可以自动解析的可选类型。你要做的只是声明的时候把感叹号放到类型的结尾,而不是每次取值的可选名字的结尾。
> 注意:
如果你在隐式解析可选类型没有值的时候尝试取值,会触发运行时错误。和你在没有值的普通可选类型后面加一个惊叹号一样。
> 如果你在隐式解析可选类型没有值的时候尝试取值,会触发运行时错误。和你在没有值的普通可选类型后面加一个惊叹号一样。
你仍然可以把隐式解析可选类型当做普通可选类型来判断它是否包含值:
@ -699,7 +720,7 @@ if let definiteString = assumedString {
```
> 注意:
如果一个变量之后可能变成`nil`的话请不要使用隐式解析可选类型。如果你需要在变量的生命周期中判断是否是`nil`的话,请使用普通可选类型。
> 如果一个变量之后可能变成`nil`的话请不要使用隐式解析可选类型。如果你需要在变量的生命周期中判断是否是`nil`的话,请使用普通可选类型。
<a name="error_handling"></a>
## 错误处理
@ -738,16 +759,16 @@ func makeASandwich() throws {
do {
try makeASandwich()
eatASandwich()
} catch Error.OutOfCleanDishes {
} catch SandwichError.outOfCleanDishes {
washDishes()
} catch Error.MissingIngredients(let ingredients) {
} catch SandwichError.missingIngredients(let ingredients) {
buyGroceries(ingredients)
}
```
在此例中,`makeASandwich()`(做一个三明治)函数会抛出一个错误消息如果没有干净的盘子或者某个原料缺失。因为`makeASandwich()`抛出错误,函数调用被包裹在`try`表达式中。将函数包裹在一个`do`语句中,任何被抛出的错误会被传播到提供的`catch`从句中。
在此例中,`makeASandwich()`(做一个三明治)函数会抛出一个错误消息如果没有干净的盘子或者某个原料缺失。因为 `makeASandwich()` 抛出错误,函数调用被包裹在 `try` 表达式中。将函数包裹在一个 `do` 语句中任何被抛出的错误会被传播到提供的 `catch` 从句中。
如果没有错误被抛出, `eatASandwich()`函数会被调用。如果一个匹配`Error.OutOfCleanDishes`的错误被抛出,`washDishes`函数会被调用。如果一个匹配`Error.MissingIngredients`的错误被抛出,`buyGroceries(_:)`函数会被调用,并且使用`catch`所捕捉到的关联值`[String]`作为参数。
如果没有错误被抛出`eatASandwich()` 函数会被调用。如果一个匹配 `SandwichError.outOfCleanDishes` 的错误被抛出`washDishes()` 函数会被调用。如果一个匹配 `SandwichError.missingIngredients` 的错误被抛出,`buyGroceries(_:)` 函数会被调用,并且使用 `catch` 所捕捉到的关联值 `[String]` 作为参数。
抛出,捕捉,以及传播错误会在[错误处理](./18_Error_Handling.html)章节详细说明。
@ -779,7 +800,7 @@ assert(age >= 0)
```
> 注意:
当代码使用优化编译的时候,断言将会被禁用,例如在 Xcode 中,使用默认的 target Release 配置选项来 build 时,断言会被禁用。
> 当代码使用优化编译的时候,断言将会被禁用,例如在 Xcode 中,使用默认的 target Release 配置选项来 build 时,断言会被禁用。
### 何时使用断言
@ -792,6 +813,4 @@ assert(age >= 0)
请参考[下标](./12_Subscripts.html)和[函数](./06_Functions.html)。
> 注意:
断言可能导致你的应用终止运行,所以你应当仔细设计你的代码来让非法条件不会出现。然而,在你的应用发布之前,有时候非法条件可能出现,这时使用断言可以快速发现问题。
> 断言可能导致你的应用终止运行,所以你应当仔细设计你的代码来让非法条件不会出现。然而,在你的应用发布之前,有时候非法条件可能出现,这时使用断言可以快速发现问题。

View File

@ -17,6 +17,8 @@
> 3.0
> 校对:[CMB](https://github.com/chenmingbiao)
>
> 版本日期2016-09-13
本页包含内容: