99> 2.0
1010> 翻译+校对:[ xtymichael] ( https://github.com/xtymichael )
1111
12+ > 2.2
13+ > 翻译:[ 175] ( https://github.com/Brian175 ) ,2016-04-09 校对:[ SketchK] ( https://github.com/SketchK ) ,2016-05-11
14+
1215本页内容包括:
1316
1417- [ 简单值(Simple Values)] ( #simple_values )
1720- [ 对象和类(Objects and Classes)] ( #objects_and_classes )
1821- [ 枚举和结构体(Enumerations and Structures)] ( #enumerations_and_structures )
1922- [ 协议和扩展(Protocols and Extensions)] ( #protocols_and_extensions )
23+ - [ 错误处理(Error Handling)] ( #error_handling )
2024- [ 泛型(Generics)] ( #generics )
2125
2226通常来说,编程语言教程中的第一个程序应该在屏幕上打印“Hello, world”。在 Swift 中,可以用一行代码实现:
@@ -30,8 +34,7 @@ print("Hello, world!")
3034这个教程会通过一系列编程例子来让你对 Swift 有初步了解,如果你有什么不理解的地方也不用担心——任何本章介绍的内容都会在后面的章节中详细讲解。
3135
3236> 注意:
33- > 为了获得最好的体验,在 Xcode 当中使用代码预览功能。代码预览功能可以让你编辑代码并实时看到运行结果。
34- > <a href =" https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/GuidedTour.playground.zip " >下载Playground</a >
37+ > 在 Mac 上,下载 Playground 并双击文件在 Xcode 里打开:[ https://developer.apple.com/go/?id=swift-tour ] ( https://developer.apple.com/go/?id=swift-tour )
3538
3639<a name =" simple_values " ></a >
3740## 简单值
@@ -142,7 +145,13 @@ if let name = optionalName {
142145> 练习:
143146> 把` optionalName ` 改成` nil ` ,greeting会是什么?添加一个` else ` 语句,当` optionalName ` 是` nil ` 时给greeting赋一个不同的值。
144147
145- 如果变量的可选值是` nil ` ,条件会判断为` false ` ,大括号中的代码会被跳过。如果不是` nil ` ,会将值赋给` let ` 后面的常量,这样代码块中就可以使用这个值了。
148+ 如果变量的可选值是` nil ` ,条件会判断为` false ` ,大括号中的代码会被跳过。如果不是` nil ` ,会将值赋给` let ` 后面的常量,这样代码块中就可以使用这个值了。
149+ 另一种处理可选值的方法是通过使用 ?? 操作符来提供一个默认值。如果可选值缺失的话,可以使用默认值来代替。
150+ ``` swift
151+ let nickName: String ? = nil
152+ let fullName: String = " John Appleseed"
153+ let informalGreeting = " Hi \( nickName ?? fullName ) "
154+ ```
146155
147156` switch ` 支持任意类型的数据以及各种比较操作——不仅仅是整数以及测试相等。
148157
@@ -188,7 +197,7 @@ print(largest)
188197```
189198
190199> 练习:
191- > 添加另一个变量来记录现在和之前最大数字的类型 。
200+ > 添加另一个变量来记录最大数字的种类(kind),同时仍然记录这个最大数字的值 。
192201
193202使用` while ` 来重复运行一段代码直到不满足条件。循环条件也可以在结尾,保证能至少循环一次。
194203
@@ -206,20 +215,14 @@ repeat {
206215print (m)
207216```
208217
209- 你可以在循环中使用` ..< ` 来表示范围,也可以使用传统的写法,两者是等价的:
218+ 你可以在循环中使用` ..< ` 来表示范围。
210219
211220``` swift
212- var firstForLoop = 0
221+ var total = 0
213222for i in 0 ..< 4 {
214- firstForLoop += i
215- }
216- print (firstForLoop)
217-
218- var secondForLoop = 0
219- for var i = 0 ; i < 4 ; ++ i {
220- secondForLoop += i
223+ total += i
221224}
222- print (secondForLoop )
225+ print (total )
223226```
224227
225228使用` ..< ` 创建的范围不包含上界,如果想包含的话需要使用` ... ` 。
@@ -534,7 +537,7 @@ let aceRawValue = ace.rawValue
534537> 练习:
535538> 写一个函数,通过比较它们的原始值来比较两个` Rank ` 值。
536539
537- 在上面的例子中,枚举原始值的类型是 ` Int ` ,所以你只需要设置第一个原始值。剩下的原始值会按照顺序赋值 。你也可以使用字符串或者浮点数作为枚举的原始值。使用` rawValue ` 属性来访问一个枚举成员的原始值。
540+ 默认情况下,Swift 按照从 0 开始每次加 1 的方式为原始值进行赋值,不过你可以通过显式赋值进行改变。 在上面的例子中,` Ace ` 被显式赋值为 1,并且剩下的原始值会按照顺序赋值 。你也可以使用字符串或者浮点数作为枚举的原始值。使用` rawValue ` 属性来访问一个枚举成员的原始值。
538541
539542使用` init?(rawValue:) ` 初始化构造器在原始值和枚举值之间进行转换。
540543
@@ -544,7 +547,7 @@ if let convertedRank = Rank(rawValue: 3) {
544547}
545548```
546549
547- 枚举的成员值是实际值,并不是原始值的另一种表达方法。实际上,以防原始值没有意义,你不需要设置 。
550+ 枚举的成员值是实际值,并不是原始值的另一种表达方法。实际上,如果没有比较有意义的原始值,你就不需要提供原始值 。
548551
549552``` swift
550553enum Suit {
@@ -595,24 +598,24 @@ let threeOfSpadesDescription = threeOfSpades.simpleDescription()
595598``` swift
596599enum ServerResponse {
597600 case Result (String , String )
598- case Error (String )
601+ case Failure (String )
599602}
600603
601604let success = ServerResponse.Result (" 6:00 am" , " 8:09 pm" )
602- let failure = ServerResponse.Error (" Out of cheese." )
605+ let failure = ServerResponse.Failure (" Out of cheese." )
603606
604607switch success {
605608case let .Result (sunrise, sunset):
606609 let serverResponse = " Sunrise is at \( sunrise ) and sunset is at \( sunset ) ."
607- case let .Error (error ):
608- let serverResponse = " Failure... \( error ) "
610+ case let .Failure (message ):
611+ print ( " Failure... \( message ) " )
609612}
610613```
611614
612615> 练习:
613616> 给` ServerResponse ` 和` switch ` 添加第三种情况。
614617
615- 注意如何从 ` ServerResponse ` 中提取日升和日落时间并用得到的值用来和 ` switch ` 的情况作比较 。
618+ 注意日升和日落时间是如何从 ` ServerResponse ` 中提取到并与 ` switch ` 的 ` case ` 相匹配的 。
616619
617620<a name =" protocols_and_extensions " ></a >
618621## 协议和扩展
@@ -683,6 +686,88 @@ print(protocolValue.simpleDescription)
683686
684687即使` protocolValue ` 变量运行时的类型是` simpleClass ` ,编译器会把它的类型当做` ExampleProtocol ` 。这表示你不能调用类在它实现的协议之外实现的方法或者属性。
685688
689+ <a name =" error_handling " ></a >
690+ ## 错误处理
691+
692+ 使用采用` ErrorType ` 协议的类型来表示错误。
693+
694+ ``` swift
695+ enum PrinterError : ErrorType {
696+ case OutOfPaper
697+ case NoToner
698+ case OnFire
699+ }
700+ ```
701+
702+ 使用` throw ` 来抛出一个错误并使用` throws ` 来表示一个可以抛出错误的函数。如果在函数中抛出一个错误,这个函数会立刻返回并且调用该函数的代码会进行错误处理。
703+
704+ ``` swift
705+ func sendToPrinter (printerName : String ) throws -> String {
706+ if printerName == " Never Has Toner" {
707+ throw PrinterError.NoToner
708+ }
709+ return " Job sent"
710+ }
711+ ```
712+
713+ 有多种方式可以用来进行错误处理。一种方式是使用` do-catch ` 。在` do ` 代码块中,使用` try ` 来标记可以抛出错误的代码。在` catch ` 代码块中,除非你另外命名,否则错误会自动命名为` error ` 。
714+
715+ ``` swift
716+ do {
717+ let printerResponse = try sendToPrinter (" Bi Sheng" )
718+ print (printerResponse)
719+ } catch {
720+ print (error)
721+ }
722+ ```
723+
724+ > 练习:
725+ > 将 printer name 改为` "Never Has Toner" ` 使` sendToPrinter(_:) ` 函数抛出错误。
726+
727+ 可以使用多个` catch ` 块来处理特定的错误。参照 switch 中的` case ` 风格来写` catch ` 。
728+
729+ ``` swift
730+ do {
731+ let printerResponse = try sendToPrinter (" Gutenberg" )
732+ print (printerResponse)
733+ } catch PrinterError.OnFire {
734+ print (" I'll just put this over here, with the rest of the fire." )
735+ } catch let printerError as PrinterError {
736+ print (" Printer error: \( printerError ) ." )
737+ } catch {
738+ print (error)
739+ }
740+ ```
741+
742+ > 练习:
743+ > 在` do ` 代码块中添加抛出错误的代码。你需要抛出哪种错误来使第一个` catch ` 块进行接收?怎么使第二个和第三个` catch ` 进行接收呢?
744+
745+ 另一种处理错误的方式使用` try? ` 将结果转换为可选的。如果函数抛出错误,该错误会被抛弃并且结果为` nil ` 。否则的话,结果会是一个包含函数返回值的可选值。
746+
747+ ``` swift
748+ let printerSuccess = try ? sendToPrinter (" Mergenthaler" )
749+ let printerFailure = try ? sendToPrinter (" Never Has Toner" )
750+ ```
751+
752+ 使用` defer ` 代码块来表示在函数返回前,函数中最后执行的代码。无论函数是否会抛出错误,这段代码都将执行。使用` defer ` ,可以把函数调用之初就要执行的代码和函数调用结束时的扫尾代码写在一起,虽然这两者的执行时机截然不同。
753+
754+ ``` swift
755+ var fridgeIsOpen = false
756+ let fridgeContent = [" milk" , " eggs" , " leftovers" ]
757+
758+ func fridgeContains (itemName : String ) -> Bool {
759+ fridgeIsOpen = true
760+ defer {
761+ fridgeIsOpen = false
762+ }
763+
764+ let result = fridgeContent.contains (itemName)
765+ return result
766+ }
767+ fridgeContains (" banana" )
768+ print (fridgeIsOpen)
769+ ```
770+
686771<a name =" generics " ></a >
687772## 泛型
688773
0 commit comments