Swift提供了多種流程控制結構,包括可以多次執行任務的while
循環,基于特定條件基于特定條件選擇執行不同代碼分支的if
guardswitch
語句,還有控制流程跳轉到其他代碼位置的
breakcontinue
語句 Swift還提供了
for-in循環,用來更簡單的遍歷數組 (Array),字典(Dictionary),集合(Set),區間 (Range),字符串 (String)和其他序列類型 Swift的
switch語句比c語言中更加強大,
case還可以匹配很多不同的模式,包括范圍匹配,元組和特定類型匹配,
switch語句的case中匹配的值可以聲明為臨時常量或變量,在case作用域內使用,也可以匹配
where`來描述更復雜的匹配條件
For-in
//遍歷數組
let arr1 = ["i","am","a","good","boy"]
for arr1Str in arr1 {
print("arr1Str:\(arr1Str)")
}
/*
arr1Str:i
arr1Str:am
arr1Str:a
arr1Str:good
arr1Str:boy
*/
//遍歷集合
let set1:Set = [1,2,3,4,5]
for set1Int in set1 {
print("set1Int:\(set1Int)")
}
/*
set1Int:5
set1Int:2
set1Int:3
set1Int:1
set1Int:4
*/
//遍歷字典
let dic1 = [1:"1",2:"2",3:"3"]
for (dicKey,dicValue) in dic1 {
print("dicKey:\(dicKey) dicValue:\(dicValue)")
}
/*
dicKey:2 dicValue:2
dicKey:3 dicValue:3
dicKey:1 dicValue:1
*/
//遍歷字符串
let str1 = "iamagoodboy"
for str1Ch in str1 {
print("str1Ch:\(str1Ch)")
}
/*
str1Ch:i
str1Ch:a
str1Ch:m
str1Ch:a
str1Ch:g
str1Ch:o
str1Ch:o
str1Ch:d
str1Ch:b
str1Ch:o
str1Ch:y
*/
//循環數字范圍
for idx in 1...5 {
print("\(idx) times 5 is \(idx*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
*/
While
while
循環會一直運行一段語句直到條件變成false
條件只能為
true
和false
,oc中只要為正數也可能表示條件為true
,swift中不行
這類循環適合使用在第一次迭代前,迭代次數未知的情況下。Swift
提供兩種while
循環形式
-
while
循環,每次在循環開始時計算條件是否符合
var whileI:Int = 10
while whileI > 0 {
print("whileI:\(whileI)")
whileI -= 1
//--whileI 在swift廢除了?????
}
/*
whileI:10
whileI:9
whileI:8
whileI:7
whileI:6
whileI:5
whileI:4
whileI:3
whileI:2
whileI:1
*/
-
repeat-while
循環,每次在循環結束時計算條件是否符合,意思就是說:它和while的區別是在判斷循環條件之前,先執行一次循環的代碼塊。然后重復循環直到條件為false,可以相當于oc中的do-while
//Repeat-While
var whilerR = false
repeat{
print("whilerR")
}while whilerR
/*
whilerR
先進去statements再判斷下次是否進入
*/
if
if
語句是最簡單的形式,只包含一個條件,只有該條件為true
,才執行相關代碼
注意,跟while的條件判斷是一樣,swift下的條件判斷只有
true
和false
,正整數并不能表示true
Switch
oc中的switch
的參數類型要求是integer type
,如果不是integer
就會報錯Statement requires expression of integer type ('NSString *__strong' invalid)
oc中的case
語句是為了匹配switch
中的參數的值,所以其條件值必須是常數(const
)
下面來說了swift中的switch
let switchT1 = 1
switch switchT1 {
case 1:
print("switchT1 == 1")
default:
print("switchT1 != 1")
}
/*
switchT1 == 1
*/
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")
}
/*
The last letter of the alphabet
*/
- 與
C
和Objective-C
中的switch
語句不同,在Swift
中,當匹配的case
分支中的代碼執行完畢后,程序會終止switch
語句,而不會繼續執行下一個case
分支。這也就是說,不需要在case
分支中顯式地使用break
語句。這使得switch
語句更安全、更易用,也避免了因忘記寫break
語句而產生的錯誤
注意: 雖然在Swift中break不是必須的,但你依然可以在 case 分支中的代碼執行完畢前使用break跳出
- 每一個
case
分支都必須包含至少一條語句。像下面這樣書寫代碼是無效的,因為第一個case
分支是空的
let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a": // 無效,這個分支下面沒有語句
case "A":
print("The letter A")
default:
print("Not the letter A")
}
// 這段代碼會報編譯錯誤
不像 C
語言里的switch
語句,在 Swift
中,switch
語句不會一起匹配"a"
和"A"
。相反的,上面的代碼會引起編譯期錯誤:case "a"
: 不包含任何可執行語句——這就避免了意外地從一個 case
分支貫穿到另外一個,使得代碼更安全、也更直觀
為了讓單個case
同時匹配a
和A
,可以將這個兩個值組合成一個復合匹配,并且用逗號分開
let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a", "A":
print("The letter A")
default:
print("Not the letter A")
}
// 輸出 "The letter A
- 區間匹配
case
分支的模式也可以是一個值的區間。下面的例子展示了如何使用區間匹配來輸出任意數字對應的自然語言格式
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).")
// 輸出 "There are dozens of moons orbiting Saturn."
- 元組
我們可以使用元組在同一個switch
語句中測試多個值。元組中的元素可以是值,也可以是區間。另外,使用下劃線(_)
來匹配所有可能的值。
下面的例子展示了如何使用一個(Int, Int)
類型的元組來分類下圖中的點(x, y)
:
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")
}
// 輸出 "(1, 1) is inside the box"
continue
continue
語句告訴一個循環體立刻停止本次循環,開始下一次循環,就好像在說“本次循環我已經執行完了”,但是并不會離開整個循環體
break
break
語句會立刻結束整個控制流的執行
- 循環語句中的
break
當在一個循環體中使用break
時,會立刻中斷該循環體的執行,然后跳轉到表示循環體結束的大括號(})
后的第一行代碼。不會再有本次循環的代碼被執行,也不會再有下次的循環產生 - Switch 語句中的
break
當在一個switch
代碼塊中使用break
時,會立即中斷該switch
代碼塊的執行,并且跳轉到表示switch
代碼塊結束的大括號(})
后的第一行代碼
fallthrough 貫穿
在 Swift 里,switch
語句不會從上一個 case
分支跳轉到下一個 case
分支中。相反,只要第一個匹配到的 case
分支完成了它需要執行的語句,整個switch
代碼塊完成了它的執行。相比之下,C
語言要求你顯式地插入break
語句到每個 case
分支的末尾來阻止自動落入到下一個 case
分支中。Swift
的這種避免默認落入到下一個分支中的特性意味著它的switch
功能要比 C
語言的更加清晰和可預測,可以避免無意識地執行多個 case
分支從而引發的錯誤。
如果你確實需要 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."
這個例子定義了一個String
類型的變量description
并且給它設置了一個初始值。函數使用switch
邏輯來判斷integerToDescribe
變量的值。當integerToDescribe
的值屬于列表中的質數之一時,該函數在description
后添加一段文字,來表明這個數字是一個質數。然后它使用fallthrough
關鍵字來“貫穿”到default
分支中。default
分支在description
的最后添加一段額外的文字,至此switch
代碼塊執行完了。
如果integerToDescribe
的值不屬于列表中的任何質數,那么它不會匹配到第一個switch
分支。而這里沒有其他特別的分支情況,所以integerToDescribe
匹配到default
分支中。
當switch
代碼塊執行完后,使用print(_:separator:terminator:)
函數打印該數字的描述。在這個例子中,數字5被準確的識別為了一個質數
注意:
fallthrough
關鍵字不會檢查它下一個將會落入執行的case
中的匹配條件。fallthrough
簡單地使代碼繼續連接到下一個 case 中的代碼,這和 C 語言標準中的switch語句特性是一樣的。
帶標簽的語句
在 Swift 中,你可以在循環體和條件語句中嵌套循環體和條件語句來創造復雜的控制流結構。并且,循環體和條件語句都可以使用break語句來提前結束整個代碼塊。因此,顯式地指明break語句想要終止的是哪個循環體或者條件語句,會很有用。類似地,如果你有許多嵌套的循環體,顯式指明continue
語句想要影響哪一個循環體也會非常有用。
為了實現這個目的,你可以使用標簽(statement label)
來標記一個循環體或者條件語句,對于一個條件語句,你可以使用break
加標簽的方式,來結束這個被標記的語句。對于一個循環語句,你可以使用break
或者continue
加標簽,來結束或者繼續這條被標記語句的執行。
聲明一個帶標簽的語句是通過在該語句的關鍵詞的同一行前面放置一個標簽,作為這個語句的前導關鍵字(introducor keyword)
,并且該標簽后面跟隨一個冒號。下面是一個針對while循環體的標簽語法,同樣的規則適用于所有的循環體和條件語句
label name: while condition { statements }
提前退出
像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."
如果guard
語句的條件被滿足,則繼續執行guard
語句大括號后的代碼。將變量或者常量的可選綁定作為guard語句的條件,都可以保護guard
語句后面的代碼。
如果條件不被滿足,在else
分支上的代碼就會被執行。這個分支必須轉移控制以退出guard
語句出現的代碼段。它可以用控制轉移語句如return
,break
,continue
或者throw
做這件事,或者調用一個不返回的方法或函數,例如fatalError()
。
相比于可以實現同樣功能的if語句,按需使用guard
語句會提升我們代碼的可讀性。它可以使你的代碼連貫的被執行而不需要將它包在else
塊中,它可以使你在緊鄰條件判斷的地方,處理違規的情況