苹果Swift语言官方文档(中文翻译版)

本文档由长沙戴维营教育组织翻译和校对,由于英语水平有限,请大家指正。

长沙戴维营教育还为本教程录制了配套的视频教程在乌班图学院上免费提供,欢迎大家一起学习。

下面的章节,如果为蓝色链接表示以及翻译完毕,可以查看,如果为黑色则表示正在紧张的翻译中。本文档中文版每天都会更新,大家可以随时查看。如由Bug欢迎改正。


Swift编程

流程控制

Swift提供C语言类似的流程控制结构。它使用forwhile执行重复操作;ifswitch实现分支判断;breakcontinue进行跳转。

除了C语言中的for-condition-increment循环形式,Swift还提供for-in快速循环,使得对数组、字典、范围、字符串或其它的序列结构进行遍历变得更加简单。

Swift的switch语句比C语言中更加强大。它不需要使用break来结束每个case。每个case能够匹配更多类型的模式,包括范围、元组等,对于复杂的条件还能使用where进行判断,而C语言中只能使用整数。

for循环

for循环可以让一组语句执行特定的次数。Swift提供了两种类型的for循环:

  • for-in遍历范围、序列、集合等数据结构。
  • for-condition-increment执行循环体,直到不满足条件。

for-in

for-in类型的循环可以对集合中的元素进行遍历,如一组数值、一个数组或者字符串。下面是循环打印五次:

  1. for index in 1...5 {
  2. println("\(index) times 5 is \(index * 5)")
  3. }
  4. // 1 times 5 is 5
  5. // 2 times 5 is 10
  6. // 3 times 5 is 15
  7. // 4 times 5 is 20
  8. // 5 times 5 is 25

提示 index常量的作用域只在循环体里面。如果需要在外面使用它的值,则应该在循环体外面定义一个遍历。

如果不需要从范围中获取值的话,可以使用下划线_代替常量index的名字,从而忽略这个常量的值:

  1. let base = 3
  2. let power = 10
  3. var answer = 1
  4. for _ in 1...power {
  5. answer *= base
  6. }
  7. println("\(base) to the power of \(power) is \(answer)")
  8. //prints "3 to the power of 10 is 59049"

下面是使用for-in遍历数组里的元素:

  1. let names = ["Anna", "Alex", "Brain", "Jack"]
  2. for name in names {
  3. println("Hello, \(name)!")
  4. }
  5. //Hello, Anna!
  6. //Hello, Alex!
  7. //Hello, Brain!
  8. //Hello, Jack!

还可以使用键值对遍历字典:

  1. let numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
  2. for (animalName, legCount) in numberOfLegs {
  3. println("\(animalName)s have \(legCount) legs")
  4. }
  5. //spiders have 8 legs
  6. //ants have 6 legs
  7. //cats have 4 legs

由于字典是无序的,因此迭代的顺序不一定和插入顺序相同。

对于字符串String进行遍历的时候,得到的是里面的字符Character

  1. for character in "Hello" {
  2. println(character)
  3. }
  4. // H
  5. // e
  6. // l
  7. // l
  8. // o

for-condition-increment

第二种形式的for循环与C语言相同,需要一个循环条件和递增的变量:

  1. for var index = 0; index < 3; ++index {
  2. println("index is \(index)")
  3. }
  4. //index is 0
  5. //index is 1
  6. //index is 2

下面是这种循环的通用格式,for循环中的分号不能省略: for 初始化; 循环条件; 递增变量 { 循环体语句 } 这些语句的执行顺序如下:

  1. 第一次进入是先执行初始化表达式,给循环中用到的常量和变量赋值。
  2. 执行循环条件表达式,如果为false,循环结束,否则执行花括号{}里的循环体语句。
  3. 循环体执行完后,递增遍历表达式执行,然后再回到上面的第2条。

这中形式的for循环可以用下面的while循环等价替换:

  1. 初始化
  2. while 循环条件 {
  3. 循环体语句
  4. 递增变量
  5. }

在初始化是声明的常量或变量的作用域为for循环里面,如果需要在循环结束后使用index的值,需要在for循环之前进行声明:

  1. var index: Int
  2. for index = 0; index < 3; ++index {
  3. println("index is \(index)")
  4. }
  5. //index is 0
  6. //index is 1
  7. //index is 2
  8. println("The loop statements were executed \(index) times")
  9. //prints "The loop statements were executed 3 times"

while循环

while循环也有两种形式:

  • while在执行循环体之前先判断循环条件。
  • do-while先执行循环体,然后再判断循环条件。

while循环

while的通用格式:

  1. while 循环条件 {
  2. 循环体语句
  3. }

do-while循环

do-while循环的通用格式:

  1. do {
  2. 循环体语句
  3. }while(循环条件)

条件判断语句

条件判断语句包括ifswitch

if语句

最简单的形式就是一个if语句,当if的判断条件为true的时候,执行if里面的语句:

  1. var temperatureInFahrenheit = 30
  2. if temperatureInFahrenheit <= 32 {
  3. println("It's very cold. Consider wearing a scarf.")
  4. }
  5. //prints "It's very cold. Consider wearing a scarf."

如果需要在if的判断条件为false的时候执行一些操作,可以加入else语句:

  1. temperatureInFahrenheit = 40
  2. if temperatureInFahrenheit <= 32 {
  3. println("It's very cold. Consider wearing a scarf.")
  4. }
  5. else {
  6. println("It's not that cold. Wear a t-shirt.")
  7. }
  8. //prints "It's not that cold. Wear a t-shirt."

如果需要增加更多的判断条件,可以将多个if-else语句链接起来:

  1. temperatureInFahrenheit = 90
  2. if temperatureInFahrenheit <= 32 {
  3. println("It's very cold. Consider wearing a scarf.")
  4. }
  5. else if temperatureInFahrenheit >= 86 {
  6. println("It's really warm. Don't forget to wear sunscreen.")
  7. }
  8. else {
  9. println("It's not that cold. Wear a t-shirt.")
  10. }
  11. //prints "It's really warm. Don't forget to wear sunscreen."

最后一个else是可选的,如果不需要执行任何操作,可以不写。

  1. temperatureInFahrenheit = 72
  2. if temperatureInFahrenheit <= 32 {
  3. println("It's very cold. Consider wearing a scarf.")
  4. } else if temperatureInFahrenheit >= 86 {
  5. println("It's really warm. Don't forget to wear sunscreen.")
  6. }

switch语句

switch语句可以将同一个值与多个判断条件进行比较,找出合适的代码进行执行。最简单的形式是将一个值与多个同类型的值进行比较:

  1. switch 需要进行判断的值 {
  2. case 1:
  3. 代码块
  4. case 1, 2:
  5. 代码块
  6. default:
  7. 代码块
  8. }

需要在switch中覆盖所有可能的值,对于没法不能在case中覆盖到的,应该在default中进行处理。

  1. let someCharacter: Character = "e"
  2. switch someCharacter {
  3. case "a", "e", "i", "o", "u":
  4. println("\(someCharacter) is a vowel")
  5. case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
  6. "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
  7. println("\(someCharacter) is a consonant")
  8. default:
  9. println("\(someCharacter) is not a vowel or a consonant")
  10. }
  11. // prints "e is a vowel"

在Swift里,switch的每个case都必须要有语句,它不像C语言一样遇到空的case就自动往下执行,下面的写法会出现编译错误:

  1. let anotherCharacter: Character = "a"
  2. switch anotherCharacter {
  3. case "a":
  4. case "A":
  5. println("The letter A")
  6. default:
  7. println("Not the letter A")
  8. }
  9. // this will report a compile-time error

同一个case可以对应多个值,每个值之间用,隔开。

提示 如果在一个case执行完后,继续执行下面的case,需要使用fallthrough关键字。

范围匹配

switch可以对一个范围进行判断,从而确定是否执行某个case下的语句:

  1. let count = 3_000_000_000_000
  2. let countedThings = "stars in the Milky Way"
  3. var naturalCount: String
  4. switch count {
  5. case 0:
  6. naturalCount = "no"
  7. case 1...3:
  8. naturalCount = "a few"
  9. case 4...9:
  10. naturalCount = "several"
  11. case 10...99:
  12. naturalCount = "tens of"
  13. case 100...999:
  14. naturalCount = "hundreds of"
  15. case 1000...999_999:
  16. naturalCount = "thousands of"
  17. default:
  18. naturalCount = "millions and millions of"
  19. }
  20. println("There are \(naturalCount) \(countedThings).")
  21. // prints "There are millions and millions of stars in the Milky Way."

提示 Swift中的整数,可以用下划线_分隔,便于查看。

元组

Swift可以在switch中对元组进行判断。元组的每个元素都会与对应的值进行比较,可以使用下划线_表示匹配任意值。下面用switch来判断一个点是否在某个范围内:

  1. let somePoint = (1, 1)
  2. switch somePoint {
  3. case (0, 0):
  4. println("(0, 0) is at the origin")
  5. case (_, 0):
  6. println("(\(somePoint.0), 0) is on the x-axis")
  7. case (0, _):
  8. println("(0, \(somePoint.1)) is on the y-axis")
  9. case (-2...2, -2...2):
  10. println("(\(somePoint.0), \(somePoint.1)) is inside the box")
  11. default:
  12. println("(\(somePoint.0), \(somePoint.1)) is outside of the box")
  13. }
  14. // prints "(1, 1) is inside the box"

苹果Swift语言官方文档(中文翻译版) - 图1

Swift中case表示的范围可以是重叠的,但是会匹配最先发现的值。

值的绑定

switch能够将值绑定到临时的常量或变量上,然后在case中使用,被称为value binding

  1. let anotherPoint = (2, 0)
  2. switch anotherPoint {
  3. case (let x, 0):
  4. println("on the x-axis with an x value of \(x)")
  5. case (0, let y):
  6. println("on the y-axis with a y value of \(y)")
  7. case let (x, y):
  8. println("somewhere else at (\(x), \(y))")
  9. }
  10. // prints "on the x-axis with an x value of 2"

苹果Swift语言官方文档(中文翻译版) - 图2

上面的代码匹配所有y等于0的元组,并将常量x初始化为2,x的作用域为它所在的case。你也可以将xvar关键字声明为变量。

where语句

switch中可以使用where增加额外的判断条件:

  1. let yetAnotherPoint = (1, -1)
  2. switch yetAnotherPoint {
  3. case let (x, y) where x == y:
  4. println("(\(x), \(y)) is on the line x == y")
  5. case let (x, y) where x == -y:
  6. println("(\(x), \(y)) is on the line x == -y")
  7. case let (x, y):
  8. println("(\(x), \(y)) is just some arbitrary point")
  9. }
  10. // prints "(1, -1) is on the line x == -y"

苹果Swift语言官方文档(中文翻译版) - 图3

流程转换语句

流程转换语句(跳转语句)可以改变代码的执行流程。Swift包含下面四种跳转语句:

  • continue
  • break
  • fallthrough
  • return

下面会对continuebreakfallthrough进行讲解,而return表达式将在函数中进行介绍。

continue表达式

continue语句可以提前结束一次循环,之间调到第二次循环开始,但是并不会终止循环。

提示for-condition-increment类型的循环中,自增语句在continue后仍然会执行。

下面的例子会删除字符串中的元音字符和空格:

  1. let puzzleInput = "great minds think alike"
  2. var puzzleOutput = ""
  3. for character in puzzleInput {
  4. switch character {
  5. case "a", "e", "i", "o", "u", " ":
  6. continue
  7. default:
  8. puzzleOutput += character
  9. }
  10. }
  11. println(puzzleOutput)
  12. // prints "grtmndsthnklk"

上面的代码在遇到元音或空格后,执行continue语句,不将它们添加到输出字符串中。

break语句

break语句之间结束整个循环,可以被用在switch和循环语句中。

循环语句中使用break

break直接结束循环,调到循环体后的语句进行执行。

switch语句中使用break

break会导致switch语句执行终止,只要用于忽略一个case的执行。因为switch中不能有空的case,所以可以用break来忽略一个case的执行。

  1. let numberSymbol: Character = "三" // Simplified Chinese for the number 3
  2. var possibleIntegerValue: Int?
  3. switch numberSymbol {
  4. case "1", "١", "一", "๑":
  5. possibleIntegerValue = 1
  6. case "2", "٢", "二", "๒":
  7. possibleIntegerValue = 2
  8. case "3", "٣", "三", "๓":
  9. possibleIntegerValue = 3
  10. case "4", "٤", "四", "๔":
  11. possibleIntegerValue = 4
  12. default:
  13. break
  14. }
  15. if let integerValue = possibleIntegerValue {
  16. println("The integer value of \(numberSymbol) is \(integerValue).")
  17. } else {
  18. println("An integer value could not be found for \(numberSymbol).")
  19. }
  20. // prints "The integer value of 三 is 3."

fallthrough语句

Swift的switch语句中不能在一个case执行完后继续执行另外一个case,这遇C语言中的情况不一样。如果你需要实现类似于C语言中switch的行为,可以使用fallthrough关键字。

  1. let integerToDescribe = 5
  2. var description = "The number \(integerToDescribe) is"
  3. switch integerToDescribe {
  4. case 2, 3, 5, 7, 11, 13, 17, 19:
  5. description += " a prime number, and also"
  6. fallthrough
  7. default:
  8. description += " an integer."
  9. }
  10. println(description)
  11. // prints "The number 5 is a prime number, and also an integer."

提示 fallthrough语句执行后,switch不会再去检查下面的case的值。

标号语句

在循环或者switch语句中使用break只能跳出最内层,如果有多个循环语句嵌套的话,需要使用标号语句才能一次性跳出这些循环。 标号语句的基本写法为:

  1. 标号名称: while 条件语句 {
  2. 循环体
  3. }

下面是标号语句的一个例子:

  1. let finalSquare = 25
  2. var board = Int[](count: finalSquare + 1, repeatedValue: 0)
  3. board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
  4. board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
  5. var square = 0
  6. var diceRoll = 0
  7. gameLoop: while square != finalSquare {
  8. if ++diceRoll == 7 { diceRoll = 1 }
  9. switch square + diceRoll {
  10. case finalSquare:
  11. // diceRoll will move us to the final square, so the game is over
  12. break gameLoop
  13. case let newSquare where newSquare > finalSquare:
  14. // diceRoll will move us beyond the final square, so roll again
  15. continue gameLoop
  16. default:
  17. // this is a valid move, so find out its effect
  18. square += diceRoll
  19. square += board[square]
  20. }
  21. }
  22. println("Game over!")

breakcontinue执行后,会跳转到标号语句处执行,其中break会终止循环,而continue则终止当前这次循环的执行。