Skip to content

Commit 77b5caf

Browse files
更新部分内容到 Swift 5.7 (#1200)
* 更新内容到 Swift 5.7 * 更新内容到 Swift 5.7 * 更新内容到 Swift 5.7 * update to Swift version 5.7 * 更新内容到 Swift 5.7 * 更新内容到 Swift 5.7 * 修正部分术语 * 更新内容到 Swift 5.7 * 更新内容到 Swift 5.7 * 标题格式修改 * 修改了部分用词 * 修改了代码块格式 * 修改了代码段及行内代码格式 * 修改了代码段及行内代码样式 * 按照排版要求重新修改了部分格式 * Delete 02_Lexical_Structure.md * Delete 03_Types.md * Delete 04_Expressions.md * Delete 05_Statements.md * Delete 07_Attributes.md * Delete 10_Summary_of_the_Grammar.md * 根据排版指南修改了部分格式 * 根据排版指南修改了部分格式 * Update source/03_language_reference/02_Lexical_Structure.md Co-authored-by: Jie Liang <lj925184928@gmail.com>
1 parent df35244 commit 77b5caf

20 files changed

+1092
-723
lines changed
2.82 MB
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
# 版本兼容性
22

3-
本书描述的是在 Xcode 13 中默认包含的 Swift 5.5 版本。你可以使用 Xcode 13 来构建 Swift 5.5、Swift 4.2 或 Swift 4 写的项目。
3+
本书描述的是在 Xcode 14 中默认包含的 Swift 5.7 版本。你可以使用 Xcode 14 来构建 Swift 5.7、Swift 4.2 或 Swift 4 写的项目。
44

5-
使用 Xcode 13 构建 Swift 4 和 Swift 4.2 代码时,Swift 5.5 的大多数功能都适用。但以下功能仅支持 Swift 5.5 或更高版本:
5+
使用 Xcode 14 构建 Swift 4 和 Swift 4.2 代码时,Swift 5.7 的大多数功能都适用。但以下功能仅支持 Swift 5.7 或更高版本:
66

77
* 返回值是不透明类型的函数依赖 Swift 5.1 运行时。
88
* **try?** 表达式不会为已返回可选类型的代码引入额外的可选类型层级。
99
* 大数字的整型字面量初始化代码的类型将会被正确推导,例如 **UInt64(0xffff_ffff_ffff_ffff)** 将会被推导为整型类型而非溢出。
1010

11-
并发特性需要 Swift 5.5 及以上版本,以及一个提供了并发相关类型的 Swift 标准库版本。要应用于苹果平台,请至少将部署版本设置为 iOS 15、macOS 12、tvOS 15 或 watchOS 8.0。
11+
并发特性需要 Swift 5.7 及以上版本,以及一个提供了并发相关类型的 Swift 标准库版本。要应用于苹果平台,请至少将部署版本设置为 iOS 15、macOS 12、tvOS 15 或 watchOS 8.0。
1212

13-
用 Swift 5.5 写的项目可以依赖用 Swift 4.2 或 Swift 4 写的项目,反之亦然。这意味着,如果你将一个大的项目分解成多个框架(framework),你可以逐个地将框架从 Swift 4 代码迁移到 Swift 5.5
13+
用 Swift 5.7 写的项目可以依赖用 Swift 4.2 或 Swift 4 写的项目,反之亦然。这意味着,如果你将一个大的项目分解成多个框架(framework),你可以逐个地将框架从 Swift 4 代码迁移到 Swift 5.7

source/01_welcome_to_swift/03_a_swift_tour.md

+53
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,14 @@ let fullName: String = "John Appleseed"
154154
let informalGreeting = "Hi \(nickName ?? fullName)"
155155
```
156156

157+
你还可以使用较短的代码解包一个值,并且对该被包装值使用相同的名称。
158+
159+
```swift
160+
if let nickname {
161+
print("Hey, \(nickName)")
162+
}
163+
```
164+
157165
`switch` 支持任意类型的数据以及各种比较操作——不仅仅是整数以及测试相等。
158166

159167
```swift
@@ -613,6 +621,51 @@ let threeOfSpadesDescription = threeOfSpades.simpleDescription()
613621
>
614622
> 写一个方法,创建一副完整的扑克牌,这些牌是所有 rank 和 suit 的组合。
615623
624+
## 并发性 {#concurrency}
625+
626+
使用 `async` 标记异步运行的函数
627+
628+
```swift
629+
func fetchUserID(from server: String) async -> Int{
630+
if server == "primary"
631+
return 97
632+
}
633+
return 501
634+
```
635+
636+
您还可以通过在函数名前添加 `await` 来标记对异步函数的调用
637+
638+
```swift
639+
func fetchUsername(from server:String) async -> String{
640+
let userID = await fetchUserID(from: server)
641+
if userID == 501{
642+
return "John Appleseed"
643+
}
644+
return "Guest"
645+
}
646+
```
647+
648+
使用 `async let` 来调用异步函数,并让其与其它异步函数并行运行
649+
使用 `await` 以使用该异步函数返回的值
650+
651+
```swift
652+
func connectUser(to server: String) async{
653+
async let userID = fetchUserID(from: server)
654+
async let username = fetchUsername(from: server)
655+
let greeting = await "Hello \(username), user ID \(userID)"
656+
print(greeting)
657+
}
658+
```
659+
660+
使用 `Task` 从同步代码中调用异步函数且不等待它们返回结果
661+
662+
```swift
663+
Task {
664+
await connectUser(to: "primary")
665+
}
666+
//Prints "Hello Guest, user ID 97"
667+
```
668+
616669
## 协议和扩展 {#protocols-and-extensions}
617670

618671
使用 `protocol` 来声明一个协议

source/02_language_guide/01_The_Basics.md

+25-3
Original file line numberDiff line numberDiff line change
@@ -587,16 +587,38 @@ if let actualNumber = Int(possibleNumber) {
587587

588588
如果转换成功,`actualNumber` 常量可以在 `if` 语句的第一个分支中使用。它已经被可选类型 *包含的* 值初始化过,所以不需要再使用 `!` 后缀来获取它的值。在这个例子中,`actualNumber` 只被用来输出转换结果。
589589

590-
你可以在可选绑定中使用常量和变量。如果你想在 `if` 语句的第一个分支中操作 `actualNumber` 的值,你可以改成 `if var actualNumber`,这样可选类型包含的值就会被赋给一个变量而非常量。
590+
如果你在访问它包含的值后不需要引用原来的可选常量或是可选变量,你可以对新的常量或是新的变量使用相同的名称:
591591

592-
你可以包含多个可选绑定或多个布尔条件在一个 `if` 语句中,只要使用逗号分开就行。只要有任意一个可选绑定的值为 `nil`,或者任意一个布尔条件为 `false`,则整个 `if` 条件判断为 `false`。下面的两个 `if` 语句是等价的:
592+
```swift
593+
let myNumber = Int(possibleNumber)
594+
// 此处 myNumber 为一可选整型
595+
if let myNumber = myNumber {
596+
// 此处 myNumber 为一不可选整型
597+
print("My number is \(myNumber)")
598+
}
599+
// 输出 "My number is 123"
600+
```
601+
602+
正如前一个例子中的代码一样,本例代码首先检查 `myNumber` 是否包含任何值。若 `myNumber` 包含有任何值,则该值将成为新常量 `myNumber` 的值。在 `if` 语句的主体中,写入的 `myNumber` 指向这一个新的非可选常量。在 `if` 语句开始前和语句结束后,写入的 `myNumber` 指向可选的整数常量。
603+
604+
由于这种代码非常常见,你可以通过一个更简短的写法来解包一个可选值:只写你要展开的常量或变量的名称。新的常量/变量将使用相同的名称作为其隐式解包可选值。
605+
606+
``` swift
607+
if let myNumber{
608+
print("My number is \(muNumber)")
609+
}
610+
// 输出 "My number is 123"
611+
```
612+
613+
你可以在可选绑定中使用常量和变量。如果你想在 `if` 语句的第一个分支中操作 `actualNumber` 的值,你可以改成 `if var actualNumber`,这样可选类型包含的值就会被赋给一个变量而非常量。你在 `if` 语句中对 `myNumber` 所做的更改将仅作用于该局部变量而非你解包的原始可选常量/变量。
614+
615+
你可以包含多个可选绑定或多个布尔条件在一个 `if` 语句中,只要使用逗号分开就行。只要有任意一个可选绑定的值为 `nil`,或者任意一个布尔条件为 `false`,则整个 `if` 条件判断为 `false`。下面的两个 `if` 语句是等效的:
593616

594617
```swift
595618
if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber && secondNumber < 100 {
596619
print("\(firstNumber) < \(secondNumber) < 100")
597620
}
598621
// 输出“4 < 42 < 100”
599-
600622
if let firstNumber = Int("4") {
601623
if let secondNumber = Int("42") {
602624
if firstNumber < secondNumber && secondNumber < 100 {

source/02_language_guide/02_Basic_Operators.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Swift 还提供了 C 语言没有的区间运算符,例如 `a..<b` 或 `a...b`
1616
- *二元*运算符操作两个操作对象(如 `2 + 3`),是*中置*的,因为它们出现在两个操作对象之间。
1717
- *三元*运算符操作三个操作对象,和 C 语言一样,Swift 只有一个三元运算符,就是三目运算符(`a ? b : c`)。
1818

19-
受运算符影响的值叫*操作数*,在表达式 `1 + 2` 中,加号 `+` 是二元运算符,它的两个操作数是值 `1``2`
19+
受运算符影响的值叫*操作数*,在表达式 `1 + 2` 中,加号 `+` 是中置运算符,它的两个操作数是值 `1``2`
2020

2121
## 赋值运算符 {#assignment-operator}
2222

source/02_language_guide/05_Control_Flow.md

+32
Original file line numberDiff line numberDiff line change
@@ -765,3 +765,35 @@ if #available(平台名称 版本号, ..., *) {
765765
APIs 不可用,使用先前版本API的语句将执行
766766
}
767767
```
768+
769+
当你在 `guard` 语句中使用可用性条件时,它将细化用于该代码块中其余代码的可用性信息。
770+
771+
```swift
772+
@avaliable(macOS 10.12, *)
773+
struct ColorPreference {
774+
var bestColor = "blue"
775+
}
776+
func chooseBestColor() -> String {
777+
guard #avaliable(macOS 10.12, *) else{
778+
return "gray"
779+
}
780+
let colors = ColorPreference()
781+
return colors.bestColor
782+
}
783+
```
784+
785+
在上面的例子中,结构体 `ColorPreference` 需要 macOS 10.12 或更高的版本。函数 `ChooseBestColor()` 先以一个可用性防护开头,若平台版本过低无法运行 `ColorPreference` 时,将执行该低版本平台可用的行为。而在 `guard` 语句后,你将能够使用 macOS 10.12 或更高版本的API。
786+
787+
除了 `#available` 以外, Swift 还支持通过不可用性条件来进行不可用性检查。举例如下,两种检查都能实现同样的效果:
788+
789+
```swift
790+
if #available(iOS 10, *){
791+
} else {
792+
//回滚代码
793+
}
794+
if #unavailable(iOS 10) {
795+
//回滚代码
796+
}
797+
```
798+
799+
若可用性检查只提供了回滚代码,改用用 `#unavailable` 能提升程序整体的可读性。

source/02_language_guide/06_Functions.md

+3
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,9 @@ print(anotherGreeting(for: "Dave"))
225225

226226
正如你将会在 [简略的 Getter 声明](./10_Properties.md) 里看到的, 一个属性的 getter 也可以使用隐式返回的形式。
227227

228+
>注意
229+
230+
>作为隐式返回值编写的代码需要返回一些值。例如,你不能使用 `print(13)` 作为隐式返回值。然而,你可以使用不返回值的函数(如 `fatalError("Oh no!")`)作为隐式返回值,因为 Swift 知道它们并不会产生任何隐式返回。
228231
229232
## 函数参数标签和参数名称 {#Function-Argument-Labels-and-Parameter-Names}
230233

source/02_language_guide/07_Closures.md

+29
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,35 @@ let strings = numbers.map {
214214

215215
在上面的例子中,通过尾随闭包语法,优雅地在函数后封装了闭包的具体功能,而不再需要将整个闭包包裹在 `map(_:)` 方法的括号内。
216216

217+
如果一个函数接受多个闭包,您需要省略第一个尾随闭包的参数标签,并为其余尾随闭包添加标签。例如,以下函数将为图片库加载一张图片:
218+
219+
```swift
220+
func loadPicture(from server: Server, completion:(Picture) -> Void,
221+
onFailure: () -> Void) {
222+
if let picture = download("photo.jpg", from: server){
223+
completion(picture)
224+
}else{
225+
onFailure()
226+
}
227+
}
228+
```
229+
230+
当您调用该函数以加载图片时,需要提供两个闭包。第一个闭包是一个完成处理程序,它在成功下载后加载图片;第二个闭包是一个错误处理程序,它向用户显示错误。
231+
232+
```swift
233+
loadPicture(from: someServer){ picture in
234+
someView.currentPicture = picture
235+
} onFailure: {
236+
print("Couldn't download the next picture.")
237+
}
238+
```
239+
240+
在本例中,`loadPicture(from:completion:onFailure:)` 函数将它的网络任务分配到后台,并在网络任务完成时调用两个完成处理程序中的一个。通过这种方法编写函数,您将能够把负责处理网络故障的代码和成功下载后更新用户界面的代码干净地区分开,而不是只使用一个闭包处理两种情况。
241+
242+
>注意
243+
>
244+
>完成处理程序可能很难阅读,特别是您必须嵌套多个完成处理程序时。另一种方法是使用异步代码,如章节[并发](./28_Concurrency.md#function-types-as-return-types) 中所述。
245+
217246
## 值捕获 {#capturing-values}
218247

219248
闭包可以在其被定义的上下文中*捕获*常量或变量。即使定义这些常量和变量的原作用域已经不存在,闭包仍然可以在闭包函数体内引用和修改这些值。

source/02_language_guide/10_Properties.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ struct Rect {
132132
var square = Rect(origin: Point(x: 0.0, y: 0.0),
133133
size: Size(width: 10.0, height: 10.0))
134134
let initialSquareCenter = square.center
135+
// initialSquareCenter 位于(5.0, 5.0)
135136
square.center = Point(x: 15.0, y: 15.0)
136137
print("square.origin is now at (\(square.origin.x), \(square.origin.y))")
137138
// 打印“square.origin is now at (10.0, 10.0)”
@@ -302,7 +303,7 @@ struct TwelveOrLess {
302303
}
303304
```
304305

305-
这个 setter 确保新值小于 12,而且返回被存储的值。
306+
这个 setter 确保新值小于或等于 12,而且返回被存储的值。
306307
> 注意
307308
>
308309
> 上面例子以 `private` 的方式声明 `number` 变量,这使得 `number` 仅在 `TwelveOrLess` 的实现中使用。写在其他地方的代码通过使用 `wrappedValue` 的 getter 和 setter 来获取这个值,但不能直接使用 `number`。有关 `private` 的更多信息,请参考 [访问控制](./26_Access_Control.md)

source/02_language_guide/14_Initialization.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@ print("Bicycle: \(bicycle.description)")
535535
// 打印“Bicycle: 2 wheel(s)”
536536
```
537537

538-
如果子类的构造器没有在阶段 2 过程中做自定义操作,并且父类有一个无参数的指定构造器,你可以在所有子类的存储属性赋值之后省略 `super.init()` 的调用。
538+
如果子类的构造器没有在阶段 2 过程中做自定义操作,并且父类有一个同步、无参数的指定构造器,你可以在所有子类的存储属性赋值之后省略 `super.init()` 的调用。若父类有一个异步的构造器,你就需要明确地写入 `await super.init()`
539539

540540
这个例子定义了另一个 `Vehicle` 的子类 `Hoverboard` ,只设置它的 `color` 属性。这个构造器依赖隐式调用父类的构造器来完成,而不是显示调用 `super.init()`
541541

source/02_language_guide/27_Advanced_Operators.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ signedOverflow = signedOverflow &- 1
276276

277277
类和结构体可以为现有的运算符提供自定义的实现。这通常被称为运算符*重载*
278278

279-
下面的例子展示了如何让自定义的结构体支持加法运算符(`+`)。算术加法运算符是一个*二元运算符*,因为它是对两个值进行运算,同时它还可以称为*中缀*运算符,因为它出现在两个值中间。
279+
下面的例子展示了如何让自定义的结构体支持加法运算符(`+`)。算术加法运算符是一个二元运算符,因为它是对两个值进行运算,同时它还可以称为中缀运算符,因为它出现在两个值中间。
280280

281281
例子中定义了一个名为 `Vector2D` 的结构体用来表示二维坐标向量 `(x, y)`,紧接着定义了一个可以将两个 `Vector2D` 结构体实例进行相加的*运算符函数*
282282

0 commit comments

Comments
 (0)