第5章:控制流
2019-02-16 本文已影响0人
行知路
Swift提供了与Objective-C类似的流程控制语句,其中最大的差别在于switch语句,以下分别对控制语句进行介绍。
5.1 For-in循环
其实是for循环的变种,主要应用于集合数据类型。
// 请注意,在for循环中不需要指定name的类型
let names = [ "Anna" , "Alex" , "Brian" , "Jack" ]
for name in names {
print ( "Hello, \( name ) !" )
}
// Hello, Anna!
// Hello, Alex!
// Hello, Brian!
// Hello, Jack!
// 对字典进行迭代
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
// 对范围进行循环
for index in 1...5 {
print("\(index) times 5 is \(index * 5)")
}
// 1 times 5 is 5
// 2 times 5 is 10
// 3 times 5 is 15
// 4 times 5 is 20
// 5 times 5 is 25
// 忽略循环的变量
let base = 3
let power = 10
var answer = 1
for _ in 1...power {
answer *= base
}
print("\(base) to the power of \(power) is \(answer)")
// Prints "3 to the power of 10 is 59049"
// 对左闭右开的范围进行循环
let minutes = 60
for tickMark in 0..<minutes {
// render the tick mark each minute (60 times)
}
// 进行指定步进值得循环
// stride返回一个序列
// 左闭右开
let minuteInterval = 5
for tickMark in stride(from: 0, to: minutes, by: minuteInterval) {
// render the tick mark every 5 minutes (0, 5, 10, 15 ... 45, 50, 55)
}
// 左闭右闭区间
let hours = 12
let hourInterval = 3
for tickMark in stride(from: 3, through: hours, by: hourInterval) {
// render the tick mark every 3 hours (3, 6, 9, 12)
}
5.2 while循环
在Swift中提了两种while循环:while与repeat-while。repeat-while与Objective-C中的do-while相同。
此两种循环的主要区别是while循环先判断条件是否满足,满足了的话,再执行语句。repeat-while循环先执行一次语句,然后再去判断是否满足条件,也就是说repeat-while保证语句至少执行一次。
while condition {
statements
}
repeat {
statements
} while condition
5.3 if条件语句
在Swift中if条件语句与Objective-C中的条件语句相同。
// if语句可以包含三种子句(if\else-if\else)
temperatureInFahrenheit = 90
if temperatureInFahrenheit <= 32 {
print ( "It's very cold. Consider wearing a scarf." )
} else if temperatureInFahrenheit >= 86 {
print ( "It's really warm. Don't forget to wear sunscreen." )
} else {
print ( "It's not that cold. Wear a t-shirt." )
}
5.4 switch语句
在Swift中除符合Objective-C中基本的switch语法外,还提供了丰富的功能。基本型的switch语法如下所示。
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
}
5.4.1 包含所有值
这就是说switch语句中的case、default语句必须包含所有的待比较的值。
// 在这个语句中default语句是必须的,不然该switch语句无法包含所有的Character的可能值,会报编译错误
let someCharacter: Character = "z"
switch someCharacter {
case "a":
print("The first letter of the alphabet")
case "z":
print("The last letter of the alphabet")
default:
print("Some other character")
}
// Prints "The last letter of the alphabet"
5.4.2 默认不穿透case语句
int value = 4;
switch (value)
{
case 4:{
NSLog(@"value is 4");
}
case 3:{
NSLog(@"value is 3");
break;
}
default:
{
NSLog(@"value is default");
}
}
// 输出如下内容
// 2019-02-15 18:19:18.905192+0800 suan-fa[81879:627747] value is 4
// 2019-02-15 18:19:19.795801+0800 suan-fa[81879:627747] value is 3
// 根据输出内容可见,在匹配了case 4之后,由于没有break语句,则继续指定case 3子句
var value: Int = 4
switch value
{
case 4:
print("value is 4")
case 3:
print("value is 3")
default:
print("value is default")
}
// 输出如下内容
// value is 4
通过以上的示例,可以看到在Swift中case子句默认是不会穿透到下一个子句中——相当于隐含有break语句。
5.4.3 case子句不得为空
// case "a":子句为空,会报语法错误
let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a": // Invalid, the case has an empty body
case "A":
print("The letter A")
default:
print("Not the letter A")
}
// This will report a compile-time error.
5.4.4 case子句匹配多个值
let anotherCharacter: Character = "a"
switch anotherCharacter {
// 通过如下方法可以实现匹配多个值
case "a", "A":
print("The letter A")
default:
print("Not the letter A")
}
5.4.5 区间匹配
let approximateCount = 62
let countedThings = "moons orbiting Saturn"
let 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).")
// Prints "There are dozens of moons orbiting Saturn."
5.4.6 元组匹配
// 如果想匹配元组中某个元素的任意值,可以使用下划线(_)
let somePoint = (1, 1)
switch somePoint {
case (0, 0):
print("\(somePoint) is at the origin")
case (_, 0):
print("\(somePoint) is on the x-axis")
case (0, _):
print("\(somePoint) is on the y-axis")
case (-2...2, -2...2):
print("\(somePoint) is inside the box")
default:
print("\(somePoint) is outside of the box")
}
5.4.7 值绑定
// 这里的值绑定与if语句中的值绑定类似
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))")
}
5.4.8 where子句
// 通过where子句示switch的功能更加强大
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")
}
// Prints "(1, -1) is on the line x == -y"
5.5 流程控制子句
在swift中有如下流程控制语句,其中return与throw后续会讲到,这里暂且不表。
- continue
- break
- fallthrough
- return
- throw
5.5.1 continue子句
// continue子句的语法功能与Objective-C中的语法功能相同
// continue子句的语法功能:跳过当前循环,进入下次循环
let puzzleInput = "great minds think alike"
var puzzleOutput = ""
let charactersToRemove: [Character] = ["a", "e", "i", "o", "u", " "]
for character in puzzleInput {
if charactersToRemove.contains(character) {
continue
}
puzzleOutput.append(character)
}
print(puzzleOutput)
// Prints "grtmndsthnklk"
5.5.2 fallthrough子句
在5.4.2中case子句默认不穿透当前子句,如果想要实现穿透的效果,需要使用fallthrough关键字。
// 请注意,在添加了fallthrough语句之后,匹配了第一个case语句之后继续向下执行,default子句也获得执行
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)
// Prints "The number 5 is a prime number, and also an integer."
5.5.3 break子句
在Swift中break具有两种作用:
- 跳出当前循环或者条件语句
- 跳出指定的循环语条件语句,此时,break语句类似以前的goto语句
// 以下示例代码中在break、continue语句中添加了标签,那么此时在执行break或者continue时,就会跳转到标签所指定的语句当中
// gameLoop就是一个标签
gameLoop: while square != finalSquare {
diceRoll += 1
if diceRoll == 7 { diceRoll = 1 }
switch square + diceRoll {
case finalSquare:
// diceRoll will move us to the final square, so the game is over
break gameLoop
case let newSquare where newSquare > finalSquare:
// diceRoll will move us beyond the final square, so roll again
continue gameLoop
default:
// this is a valid move, so find out its effect
square += diceRoll
square += board[square]
}
}
print("Game over!")
// while语句标签示例,其他语句的标签相同
label name: while condition {
statements
}
5.6 guard语句
在编写代码过程中,经常会出现需要对某些情况作出判断,如果情况允许则继续,如果相反则退出。在Swfit中针对此种情况专门提供了guard语句。
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(person: ["name": "John"])
// Prints "Hello John!"
// Prints "I hope the weather is nice near you."
greet(person: ["name": "Jane", "location": "Cupertino"])
// Prints "Hello Jane!"
// Prints "I hope the weather is nice in Cupertino."
5.7 检查API可用性
代码编写过程中经常会碰到API可用性判定的问题,在Swift中也提供了对API进行检查的语法。
if #available(platform name version, ..., *) {
statements to execute if the APIs are available
} else {
fallback statements to execute if the APIs are unavailable
}
if #available(iOS 10, macOS 10.12, *) {
// Use iOS 10 APIs on iOS, and use macOS 10.12 APIs on macOS
} else {
// Fall back to earlier iOS and macOS APIs
}