1.For-In 循环
可以使用for-in 循环来遍历一个集合中的所有元素,例如数字范围、数组中的元素或者字符串中的字符。
for index in 1...5 {
print("(index) times 5 is (index * 5)")
}
如果你不需要区间序列内每一项的值,你可以使用下划线( _ )替代变量名来忽略这个值:
let base = 3
let power = 10
var answer = 1
for _ in 1...power {
answer *= base
}
print("(base) to the power of (power) is (answer)")
// 输出 "3 to the power of 10 is 59049"
使用for-in 遍历一个数组所有元素:
let names = ["Anna", "Alex", "Brian", "Jack"]
for name in names {
print("Hello, (name)!")
}
也可以通过遍历一个字典来访问它的键值对。遍历字典时,字典的每项元素会以(key, value) 元组的形式返回,你可以在for-in 循环中使用显式的常量名称来解读(key, value) 元组
let numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
for (animalName, legCount) in numberOfLegs {
print("(animalName)s have (legCount) legs")
}
// ants have 6 legs
// cats have 4 legs
// spiders have 8 legs
2.While 循环
while 循环会一直运行一段语句直到条件变成false 。这类循环适合使用在第一次迭代前,迭代次数未知的情况下。Swift 提供两种while 循环形式:
• while 循环,每次在循环开始时计算条件是否符合;
• repeat-while 循环,每次在循环结束时计算条件是否符合。
2.1While
while 循环从计算一个条件开始。如果条件为true ,会重复运行一段语句,直到条件变为false 。
while condition {
statements
}
2.2Repeat-While
它和while 的区别是在判断循环条件之前,先执行一次循环的代码块。然后重复循环直到条件为false 。
repeat {
statements
} while condition
3.条件语句
Swift 提供两种类型的条件语句: if 语句和switch 语句。通常,当条件较为简单且可能的情况很少时,使用if 语句。而switch 语句更适用于条件较复杂、有更多排列组合的时候。并且switch 在需要用到模式匹配(pattern-matching)的情况下会更有用。
3.1If
if 语句最简单的形式就是只包含一个条件,只有该条件为true 时,才执行相关代码:
var temperatureInFahrenheit = 30
if temperatureInFahrenheit <= 32 {
print("It's very cold. Consider wearing a scarf.")
}
// 输出 "It's very cold. Consider wearing a scarf."
3.2Switch
switch 语句会尝试把某个值与若干个模式(pattern)进行匹配。根据第一个匹配成功的模式, switch 语句会执行对应的代码。当有可能的情况较多时,通常用switch 语句替换if 语句。
switch some value to consider {
case value 1:
respond to value 1
case value 2,
value 3:
respond to value 2 or 3
default:
otherwise, do something else
}
注意:与 C 和 Objective-C 中的switch 语句不同,在 Swift 中,当匹配的 case 分支中的代码执行完毕后,
程序会终止switch 语句,而不会继续执行下一个 case 分支。
这也就是说,不需要在 case 分支中显式地使用break 语句。
这使得switch 语句更安全、更易用,也避免了因忘记写break 语句而产生的错误。
区间匹配
case 分支的模式也可以是一个值的区间。下面的例子展示了如何使用区间匹配来输出任意数字对应的自然语言格式:
let approximateCount = 62
let countedThings = "moons orbiting Saturn"
var naturalCount: String
switch approximateCount {
case 0:
naturalCount = "no"
case 1..<5:
naturalCount = "a few"
case 5..<12:
naturalCount = "several"
case 12..<100:
naturalCount = "dozens of"
case 100..<1000:
naturalCount = "hundreds of"
default:
naturalCount = "many"
}
print("There are \(naturalCount) \(countedThings).")
// 输出 "There are dozens of moons orbiting Saturn."
元组
我们可以使用元组在同一个switch 语句中测试多个值。元组中的元素可以是值,也可以是区间。另外,使用下划线( _ )来匹配所有可能的值。
//展示了如何使用一个(Int, Int) 类型的元组来分类下图中的点(x, y):
let somePoint = (1, 1)
switch somePoint {
case (0, 0):
print("(0, 0) is at the origin")
case (_, 0):
print("(\(somePoint.0), 0) is on the x-axis")
case (0, _):
print("(0, \(somePoint.1)) is on the y-axis")
case (-2...2, -2...2):
print("(\(somePoint.0), \(somePoint.1)) is inside the box")
default:
print("(\(somePoint.0), \(somePoint.1)) is outside of the box")
}
// 输出 "(1, 1) is inside the box"
值绑定(Value Bindings)
case 分支允许将匹配的值绑定到一个临时的常量或变量,并且在case分支体内使用 —— 这种行为被称为值绑定(value binding),因为匹配的值在case分支体内,与临时的常量或变量绑定。
//展示了如何在一个(Int, Int) 类型的元组中使用值绑定来分类下图中的点(x, y):
let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
print("on the x-axis with an x value of \(x)")
case (0, let y):
print("on the y-axis with a y value of \(y)")
case let (x, y):
print("somewhere else at (\(x), \(y))")
}
// 输出 "on the x-axis with an x value of 2"
Where
case 分支的模式可以使用where 语句来判断额外的条件。
let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
print("(\(x), \(y)) is on the line x == y")
case let (x, y) where x == -y:
print("(\(x), \(y)) is on the line x == -y")
case let (x, y):
print("(\(x), \(y)) is just some arbitrary point")
}
// 输出 "(1, -1) is on the line x == -y"
复合匹配
当多个条件可以使用同一种方法来处理时,可以将这几种可能放在同一个case 后面,并且用逗号隔开。当case后面的任意一种模式匹配的时候,这条分支就会被匹配。并且,如果匹配列表过长,还可以分行书写:
let someCharacter: Character = "e"
switch someCharacter {
case "a", "e", "i", "o", "u":
print("\(someCharacter) is a vowel")
case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m","n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
print("\(someCharacter) is a consonant")
default:
print("\(someCharacter) is not a vowel or a consonant")
}
// 输出 "e is a vowel"
4.控制转移语句
控制转移语句改变你代码的执行顺序,通过它可以实现代码的跳转。Swift 有五种控制转移语句:
• continue
• break
• fallthrough
• return
• throw
4.1Continue
continue 语句告诉一个循环体立刻停止本次循环,重新开始下次循环。就好像在说“本次循环我已经执行完了”,但是并不会离开整个循环体。
let puzzleInput = "great minds think alike"
var puzzleOutput = ""
for character in puzzleInput.characters {
switch character {
case "a", "e", "i", "o", "u", " ":
continue
default:
puzzleOutput.append(character)
}
}
print(puzzleOutput)
// 输出 "grtmndsthnklk"
4.2Break
break 语句会立刻结束整个控制流的执行。当你想要更早的结束一个switch 代码块或者一个循环体时,你都可以使用break 语句。
<1>循环语句中的 break
当在一个循环体中使用break 时,会立刻中断该循环体的执行,然后跳转到表示循环体结束的大括号( } )后的第一行代码。不会再有本次循环的代码被执行,也不会再有下次的循环产生。
<2>Switch 语句中的 break
当在一个switch 代码块中使用break 时,会立即中断该switch 代码块的执行,并且跳转到表示switch 代码块结束的大括号( } )后的第一行代码。
4.3fallthrough-贯穿
如果你确实需要 C 风格的贯穿的特性,你可以在每个需要该特性的 case 分支中使用fallthrough 关键字。下面的例子使用fallthrough 来创建一个数字的描述语句。
let integerToDescribe = 5
var description = "The number \(integerToDescribe) is"
switch integerToDescribe {
case 2, 3, 5, 7, 11, 13, 17, 19:
description += " a prime number, and also"
fallthrough
default:
description += " an integer."
}
print(description)
// 输出 "The number 5 is a prime number, and also an integer."
注意: fallthrough 关键字不会检查它下一个将会落入执行的 case 中的匹配条件。fallthrough 简单地使代码继续连接到下一个 case 中的代码,这和 C 语言标准中的switch 语句特性是一样的。
4.4带标签的语句
你可以使用标签(statement label)来标记一个循环体或者条件语句,对于一个条件语句,你可以使用break 加标签的方式,来结束这个被标记的语句。对于一个循环语句,你可以使用break 或者continue 加标签,来结束或者继续这条被标记语句的执行。
gameLoop: while square != finalSquare {
diceRoll += 1
if diceRoll == 7 { diceRoll = 1 }
switch square + diceRoll {
case finalSquare:
// 骰子数刚好使玩家移动到最终的方格里,游戏结束。
break gameLoop
case let newSquare where newSquare > finalSquare:
// 骰子数将会使玩家的移动超出最后的方格,那么这种移动是不合法的,玩家需要重新掷骰子
continue gameLoop
default:
// 合法移动,做正常的处理
square += diceRoll
square += board[square]
}
}
print("Game over!")
5.0提前退出
像if 语句一样, guard 的执行取决于一个表达式的布尔值。我们可以使用guard 语句来要求条件必须为真时,以执行guard 语句后的代码。不同于if 语句,一个guard 语句总是有一个else 从句,如果条件不为真则执行else 从句中的代码。
func greet(person: [String: String]) {
guard let name = person["name"] else {
return
}
print("Hello \(name)")
guard let location = person["location"] else {
print("I hope the weather is nice near you.")
return
}
print("I hope the weather is nice in \(location).")
}
greet(["name": "John"])
// 输出 "Hello John!"
// 输出 "I hope the weather is nice near you."
greet(["name": "Jane", "location": "Cupertino"])
// 输出 "Hello Jane!"
// 输出 "I hope the weather is nice in Cupertino."
6.0检测 API 可用性
我们在if 或guard 语句中使用可用性条件(availability condition) 去有条件的执行一段代码,来在运行时判断调用的API是否可用。编译器使用从可用性条件语句中获取的信息去验证,在这个代码块中调用的 API 是否可用。
if #available(iOS 10, macOS 10.12, *) {
// 在 iOS 使用 iOS 10 的 API, 在 macOS 使用 macOS 10.12 的 API
} else {
// 使用先前版本的 iOS 和 macOS 的 API
}