1.For-In 循環(huán)
可以使用for-in 循環(huán)來(lái)遍歷一個(gè)集合中的所有元素,例如數(shù)字范圍、數(shù)組中的元素或者字符串中的字符。
for index in 1...5 {
print("(index) times 5 is (index * 5)")
}
如果你不需要區(qū)間序列內(nèi)每一項(xiàng)的值,你可以使用下劃線( _ )替代變量名來(lái)忽略這個(gè)值:
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 遍歷一個(gè)數(shù)組所有元素:
let names = ["Anna", "Alex", "Brian", "Jack"]
for name in names {
print("Hello, (name)!")
}
也可以通過(guò)遍歷一個(gè)字典來(lái)訪問它的鍵值對(duì)。遍歷字典時(shí),字典的每項(xiàng)元素會(huì)以(key, value) 元組的形式返回,你可以在for-in 循環(huán)中使用顯式的常量名稱來(lái)解讀(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 循環(huán)
while 循環(huán)會(huì)一直運(yùn)行一段語(yǔ)句直到條件變成false 。這類循環(huán)適合使用在第一次迭代前,迭代次數(shù)未知的情況下。Swift 提供兩種while 循環(huán)形式:
? while 循環(huán),每次在循環(huán)開始時(shí)計(jì)算條件是否符合;
? repeat-while 循環(huán),每次在循環(huán)結(jié)束時(shí)計(jì)算條件是否符合。
2.1While
while 循環(huán)從計(jì)算一個(gè)條件開始。如果條件為true ,會(huì)重復(fù)運(yùn)行一段語(yǔ)句,直到條件變?yōu)閒alse 。
while condition {
statements
}
2.2Repeat-While
它和while 的區(qū)別是在判斷循環(huán)條件之前,先執(zhí)行一次循環(huán)的代碼塊。然后重復(fù)循環(huán)直到條件為false 。
repeat {
statements
} while condition
3.條件語(yǔ)句
Swift 提供兩種類型的條件語(yǔ)句: if 語(yǔ)句和switch 語(yǔ)句。通常,當(dāng)條件較為簡(jiǎn)單且可能的情況很少時(shí),使用if 語(yǔ)句。而switch 語(yǔ)句更適用于條件較復(fù)雜、有更多排列組合的時(shí)候。并且switch 在需要用到模式匹配(pattern-matching)的情況下會(huì)更有用。
3.1If
if 語(yǔ)句最簡(jiǎn)單的形式就是只包含一個(gè)條件,只有該條件為true 時(shí),才執(zhí)行相關(guān)代碼:
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 語(yǔ)句會(huì)嘗試把某個(gè)值與若干個(gè)模式(pattern)進(jìn)行匹配。根據(jù)第一個(gè)匹配成功的模式, switch 語(yǔ)句會(huì)執(zhí)行對(duì)應(yīng)的代碼。當(dāng)有可能的情況較多時(shí),通常用switch 語(yǔ)句替換if 語(yǔ)句。
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 語(yǔ)句不同,在 Swift 中,當(dāng)匹配的 case 分支中的代碼執(zhí)行完畢后,
程序會(huì)終止switch 語(yǔ)句,而不會(huì)繼續(xù)執(zhí)行下一個(gè) case 分支。
這也就是說(shuō),不需要在 case 分支中顯式地使用break 語(yǔ)句。
這使得switch 語(yǔ)句更安全、更易用,也避免了因忘記寫break 語(yǔ)句而產(chǎn)生的錯(cuò)誤。
區(qū)間匹配
case 分支的模式也可以是一個(gè)值的區(qū)間。下面的例子展示了如何使用區(qū)間匹配來(lái)輸出任意數(shù)字對(duì)應(yīng)的自然語(yǔ)言格式:
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."
元組
我們可以使用元組在同一個(gè)switch 語(yǔ)句中測(cè)試多個(gè)值。元組中的元素可以是值,也可以是區(qū)間。另外,使用下劃線( _ )來(lái)匹配所有可能的值。
//展示了如何使用一個(gè)(Int, Int) 類型的元組來(lái)分類下圖中的點(diǎn)(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 分支允許將匹配的值綁定到一個(gè)臨時(shí)的常量或變量,并且在case分支體內(nèi)使用 —— 這種行為被稱為值綁定(value binding),因?yàn)槠ヅ涞闹翟赾ase分支體內(nèi),與臨時(shí)的常量或變量綁定。
//展示了如何在一個(gè)(Int, Int) 類型的元組中使用值綁定來(lái)分類下圖中的點(diǎn)(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 語(yǔ)句來(lái)判斷額外的條件。
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"
復(fù)合匹配
當(dāng)多個(gè)條件可以使用同一種方法來(lái)處理時(shí),可以將這幾種可能放在同一個(gè)case 后面,并且用逗號(hào)隔開。當(dāng)case后面的任意一種模式匹配的時(shí)候,這條分支就會(huì)被匹配。并且,如果匹配列表過(guò)長(zhǎng),還可以分行書寫:
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.控制轉(zhuǎn)移語(yǔ)句
控制轉(zhuǎn)移語(yǔ)句改變你代碼的執(zhí)行順序,通過(guò)它可以實(shí)現(xiàn)代碼的跳轉(zhuǎn)。Swift 有五種控制轉(zhuǎn)移語(yǔ)句:
? continue
? break
? fallthrough
? return
? throw
4.1Continue
continue 語(yǔ)句告訴一個(gè)循環(huán)體立刻停止本次循環(huán),重新開始下次循環(huán)。就好像在說(shuō)“本次循環(huán)我已經(jīng)執(zhí)行完了”,但是并不會(huì)離開整個(gè)循環(huán)體。
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 語(yǔ)句會(huì)立刻結(jié)束整個(gè)控制流的執(zhí)行。當(dāng)你想要更早的結(jié)束一個(gè)switch 代碼塊或者一個(gè)循環(huán)體時(shí),你都可以使用break 語(yǔ)句。
<1>循環(huán)語(yǔ)句中的 break
當(dāng)在一個(gè)循環(huán)體中使用break 時(shí),會(huì)立刻中斷該循環(huán)體的執(zhí)行,然后跳轉(zhuǎn)到表示循環(huán)體結(jié)束的大括號(hào)( } )后的第一行代碼。不會(huì)再有本次循環(huán)的代碼被執(zhí)行,也不會(huì)再有下次的循環(huán)產(chǎn)生。
<2>Switch 語(yǔ)句中的 break
當(dāng)在一個(gè)switch 代碼塊中使用break 時(shí),會(huì)立即中斷該switch 代碼塊的執(zhí)行,并且跳轉(zhuǎn)到表示switch 代碼塊結(jié)束的大括號(hào)( } )后的第一行代碼。
4.3fallthrough-貫穿
如果你確實(shí)需要 C 風(fēng)格的貫穿的特性,你可以在每個(gè)需要該特性的 case 分支中使用fallthrough 關(guān)鍵字。下面的例子使用fallthrough 來(lái)創(chuàng)建一個(gè)數(shù)字的描述語(yǔ)句。
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 關(guān)鍵字不會(huì)檢查它下一個(gè)將會(huì)落入執(zhí)行的 case 中的匹配條件。fallthrough 簡(jiǎn)單地使代碼繼續(xù)連接到下一個(gè) case 中的代碼,這和 C 語(yǔ)言標(biāo)準(zhǔn)中的switch 語(yǔ)句特性是一樣的。
4.4帶標(biāo)簽的語(yǔ)句
你可以使用標(biāo)簽(statement label)來(lái)標(biāo)記一個(gè)循環(huán)體或者條件語(yǔ)句,對(duì)于一個(gè)條件語(yǔ)句,你可以使用break 加標(biāo)簽的方式,來(lái)結(jié)束這個(gè)被標(biāo)記的語(yǔ)句。對(duì)于一個(gè)循環(huán)語(yǔ)句,你可以使用break 或者continue 加標(biāo)簽,來(lái)結(jié)束或者繼續(xù)這條被標(biāo)記語(yǔ)句的執(zhí)行。
gameLoop: while square != finalSquare {
diceRoll += 1
if diceRoll == 7 { diceRoll = 1 }
switch square + diceRoll {
case finalSquare:
// 骰子數(shù)剛好使玩家移動(dòng)到最終的方格里,游戲結(jié)束。
break gameLoop
case let newSquare where newSquare > finalSquare:
// 骰子數(shù)將會(huì)使玩家的移動(dòng)超出最后的方格,那么這種移動(dòng)是不合法的,玩家需要重新擲骰子
continue gameLoop
default:
// 合法移動(dòng),做正常的處理
square += diceRoll
square += board[square]
}
}
print("Game over!")
5.0提前退出
像if 語(yǔ)句一樣, guard 的執(zhí)行取決于一個(gè)表達(dá)式的布爾值。我們可以使用guard 語(yǔ)句來(lái)要求條件必須為真時(shí),以執(zhí)行g(shù)uard 語(yǔ)句后的代碼。不同于if 語(yǔ)句,一個(gè)guard 語(yǔ)句總是有一個(gè)else 從句,如果條件不為真則執(zhí)行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檢測(cè) API 可用性
我們?cè)趇f 或guard 語(yǔ)句中使用可用性條件(availability condition) 去有條件的執(zhí)行一段代碼,來(lái)在運(yùn)行時(shí)判斷調(diào)用的API是否可用。編譯器使用從可用性條件語(yǔ)句中獲取的信息去驗(yàn)證,在這個(gè)代碼塊中調(diào)用的 API 是否可用。
if #available(iOS 10, macOS 10.12, *) {
// 在 iOS 使用 iOS 10 的 API, 在 macOS 使用 macOS 10.12 的 API
} else {
// 使用先前版本的 iOS 和 macOS 的 API
}