https://developer.apple.com/library/prerelease/content/documentation/Swift/Conceptual/Swift_Programming_Language/ControlFlow.html#//apple_ref/doc/uid/TP40014097-CH9-ID120
跟C/Java语法一样, Swift提供了多种流程控制的语法, 包括while循环、if逻辑判断、break跳出循环和continue回到判断条件继续循环等。
Swift还支持for-in循环语法, 从而遍历数组、字典、区间、字符串和其它序列变得很方便。
Swift的switch/case关键字做的很强大, 不需要break关键字!!!跟Java/C/OC的用法完全不一样。 case后面可以是个语句、甚至还能用where(感觉像SQL有没有? 在Java/C/OC里是没有where关键字的!), 而Java/C的case只能是数字。
前面4篇已经提到了Swift支持for-in循环, 这里再详细描述一下for-in的所有用法:
第1种用法: 在in后面返值数字区间...或者..<运算符, 表示循环多少次。
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
看过前面4篇笔记后, 这2行代码大概能猜出来, index的取值范围就是1...5即[1,5], 因为是整型每次循环自增1, 所以index值按先后顺序是1/2/3/4/5。 如果换成for index in 1..<5会怎样? index值会是1/2/3/4,即循环4次。
有些情况下我们只需要循环N次, 循环中不关心当前是第几次, 即不需要变量index。 Swift语言使用下划线作为for-in语句的占位符(PS:感觉是抄了SQL语法, 当然Java/C/OC是不支持该特性的)
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"
// 上面示例使用_替换了index,是为了说明循环10次却不用当前次数的情况,结果等于3^10。
// 我觉得可以忽略这个写法,只使用带参数index的语法。 因为大多数情况下还是需要用当前次数的,多个参数
又能怎样? 是吧!
第2种用法: 遍历Array、Set或者Dictionary, 跟Java遍历ArrayList语法一样。
let names = ["Anna", "Alex", "Brian", "Jack"] //names是[String]数组,在Swifit创建数组是用[],而Java是
用{}
for name in names {
print("Hello, \(name)!")
}
// Hello, Anna!
// Hello, Alex!
// Hello, Brian!
// Hello, Jack!
说明: 上面这个语法跟Java相同, 相信很好理解。
Swift还能通过上述方式遍历Dictionary, 想想Java的HashMap能是否for-in方法遍历吗? 答:可以的, for循环里遍历HashMap的key(详看我的另一篇博客”HashMap源码分析”)。语法如下:
let numberOfLegs = ["spider": 8, "ant": 6, "cat": 4] //numberOfLegs是Dictionary<String,Int>类型,
注意key-value之间用冒号分隔, 键值对之间以逗号分隔。
for (animalName, legCount) in numberOfLegs { //animalName是String类型变量,legCount是Int型变量
print("\(animalName)s have \(legCount) legs")
}
// ants have 6 legs
// spiders have 8 legs
// cats have 4 legs
While循环, Swift参考了C语言的while和do-while语法, 支持while和repeat-while语法。 如果你懂C或Object-C, 就很好理解了。 Swift语言的while对应C语言的while, Swift语言的repeat-while对应C语言的do-while。
while和repeat-while的唯一区别是while要先判断再执行循环, repeat-while是先执行循环再判断。 所以判断条件为false时, while不会执行循环体, 但repeat-while会执行一次循环体。
var square = 0
var diceRoll = 0
while square < finalSquare {
print("first execute")
}
无输出!
repeat {
print("first execute")
} while square < finalSquare
输出 "first execute"
这就是while和repeat-while的唯一区别!
If
Swift跟C/OC/Java的If关键字功能、用法是一致的, 就是判断if后面值为true or false来执行函数体, true执行if函数体, false执行else函数体。 Swift还支持if/else if/else, 语法也跟C/Java一模一样。
temperatureInFahrenheit = 40
if temperatureInFahrenheit <= 32 {
print("true execute")
} else {
print("false execute")
}
<code class="code-voice"><span class="c">// 因为42大于32,temperatureInFahrenheit <= 32为false, 所以执行else函数体,输出"false execute"
</span></code><code class="code-voice"><span class="c"></span></code><pre name="code" class="java">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.")
}
因为temperatureInFahrenheit不满足前2个if判断,执行了else分之语句,输出"It's not that cold. Wear a t-shirt."
Switch
相对于C/Java/OC语言来说, Swift对switch-case做了很多改进,case后面可以跟一条语句且支持Character类型。 下面仔细说明Swift对switch-case都做了哪些改造。
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
}
<pre name="code" class="java">let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a", "A":
print("The letter A")
default:
print("Not the letter A")
}
//这是基本用法, 跟Java/C/OC是类似。区别是Swift没执行<span style="color:#ff0000;"><strong>break</strong></span>,多个值时如<span style="font-family: Arial, Helvetica, sans-serif;">2/3中间用<strong><span style="color:#ff0000;">逗号</span></strong>分开作为一个case; 而Java是分成2个case,Java写法如下</span>
swith some value to consider {
case value 1:
respond to value 1
break;
case value 2:
case value 3:
response to value 2 or 3
break;
default:
}
Swift的case后面还可以跟Character类型(Java/C仅支持整型), 例如
let someCharacter: Character = "z" //注意:Swift里的字符型Character使用双引号, 而Java/C使用单引号!
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")
}
// 输出"The last letter of the alphabe
前面提到了Swift的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"
}
<pre name="code" class="java">print("There are \(naturalCount) \(countedThings).")
// 因为62符合case 12..<100条件,所以输出"There are dozens of moons orbiting Saturn."
switch-case语法还支持键值对, 也是用下划线做占位符。
let somePoint = (1, 1) //理解为(x, y)格式
switch somePoint {
case (0, 0):
print("(0, 0) is at the origin")
case (_, 0):
print("(\(somePoint.0), 0) is on the x-axis") //somePoint.0得到x
case (0, _):
print("(0, \(somePoint.1)) is on the y-axis") //somePoint.1得到y
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")
}
<pre name="code" class="java">// 输出"(1, 1) is inside the box"
如果要判断(x, y)其中一个值等于某值, 然后取另一个值该如何做? Swift也做了支持, 语法如下
let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0): //含义是当anotherPoint.1等于0时, 将anotherPoint.0赋值给x,并执行case下的语句
print("on the x-axis with an x value of \(x)")
case (0, let y): //含义是当anotherPoint.0等于0时, 将anotherPoint.1赋值给x,并执行case下的语句
print("on the y-axis with a y value of \(y)")
case let (x, y): //含义是任意数值将anotherPoint.0赋值给x,anotherPoint.1赋值给y。注意let放在圆括号的左边!在本switch中相当于default, 如果前面的case都是false, 那么就会执行到里面,例如anotherPoint是(3, 3),那么会输出"somewhere else at (3, 3)
print("somewhere else at (\(x), \(y))")
}
// 因为(2, 0)符合(let x, 0)的条件, 所以输出"on the x-axis with an x value of 2"
Switch还对switch-case的let做了个高级功能, 添加where关键字(可以理解为当, 即后续语句条件满足时)。 解决有些时候需要判断2个值的关系时的逻辑,懂得SQL语言的话就很好理解, 语法如下:
let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y: //当yetAnotherPoint.0等于yetAnotherPoint.1时执行
print("(\(x), \(y)) is on the line x == y")
case let (x, y) where x == -y: //当yetAnotherPoint.0等于yetAnotherPoint.1负数时执行
print("(\(x), \(y)) is on the line x == -y")
case let (x, y): //相当于default语句, 如果前面case都是false则会执行。
print("(\(x), \(y)) is just some arbitrary point")
}
//1和-1符合x==-y的条件, 所以会输出"1, -1 is on the line x == -y"
前面提到了case后面可以跟多个值,中间用逗号分隔; 这个值还可以是键值对! 比如
let stillAnotherPoint = (9, 0)
switch stillAnotherPoint {
case (let distance, 0), (0, let distance): //2个键值对,sitllAnotherPoint.0或.1等于0时为真
print("On an axis, \(distance) from the origin")
case (let distance, 1) //stillAnotherPoint.1等于1时为真
print("when y equals 1, \(distance) test 1")
case (2, let distance) //stillAnotherPoint.0等于2时为真
print("when x equals 2, \(distance) test 2")
default:
print("Not on an axis")
}
因为第1个case为真, 所以输出:"On an axis, 9 from the origin"
练习:
var sValue = "a"
switch sValue {
case "a", "b", "c":
print("a first") //不需要break关键字
case "a":
print("a0")
print("a1")
case "b", "a":
print("bbbb")
default:
print("default")
}
输出: a first
说明: 跟Java/C不同的是,Swift的每个case都是个代码块, 并会在最后跳出switch;必须有default, 否则XCode提示错误;
Swift的break、continue跟其它语言完全一样, 可以不废话了。
Fallthrough关键字, 作用类似于try/catch/finally里的finally或者C语言里的goto, 即肯定会跳转到最后执行!而且仅用在switch/case语句里。语法如下:
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语句里, 有点像C语言的goto
default:
description += " an integer."
}
print(description)
// 输出"The number 5 is a prime number, and also an integer."
Lable语句, Swift提供了类似于C语言goto的语法, 用在while循环里, 实现中断循环并跳转到前面的while判断继续执行的功能。
label name: while condition {
statements
}
上面是语法格式
gameLoop: while square != finalSquare {
diceRoll += 1
if diceRoll == 7 { diceRoll = 1 }
switch square + diceRoll {
case finalSquare:
// 跟Java一样跳出while循环
break gameLoop
case let newSquare where newSquare > finalSquare:
// 跟Java类似,跳转到while语句
continue gameLoop
default:
// this is a valid move, so find out its effect
square += diceRoll
square += board[square]
}
}
在Java函数体前几句经常是判断某些参数是否为空,为空时return即退出函数体。 Swift对这种情况创造了新的语法进行支持, 提供guard关键字,功能类似于if, 区别是guard后面总跟着是else语句。 当然你也可以不用guard关键字, 使用if关键字完全可以实现判空的功能。
func greet(person: [String: String]) { //Java里使用func声明函数, greet是函数名称
guard let name = person["name"] else { //该语句的意思是将person["name"]赋值给name, 当name为nil时执行else语句,不是nil时跳过继续向下执行, 即做了Java的参数判空逻辑
return
}
...
}
小结:
1、switch/case默认必须带default分支,否则编译报错; 只有一种情况除外, 即switch的是枚举!
2、guard关键字用于函数参数逻辑判空(类似于Java);
3、continue/break实现类似于c语言的goto功能;