Swift--控制流 (Control Flow)
文章摘要
- For-In 迴圈
- While
- if
- Switch
- 控制轉移語句
注意點
- repeat-while 迴圈
- 在 Swift 中,當匹配的 case 分支中的程式碼執行完畢後,程式會終止switch語句,而不會繼續執行下一個 case 分支。
- 區間匹配
- 值繫結 (Value Bindings)
- where
- fallthrough
- 帶標籤的語句
- guard else
- #available(iOS 10, macOS 10.12, *)
For-In 迴圈
let names = ["Anna", "Alex", "Brian", "Jack"]
for name in names {
print("Hello, \(name)!")
}
//可以在 for-in 迴圈中使用顯式的常量名稱來解讀 (key, value) 元組
let numberOfLegs = ["spider": 8, "ant": 6, "cat":4]
for (animalName, legCount) in numberOfLegs {
print("\(animalName)s have \(legCount) legs")
}
//迴圈還可以使用數字範圍
for index in 1...5 {
print("\(index) times 5 is \(index * 5)")
}
//可以使用下劃線(_)替代變數名來忽略這個值
let base = 3
let power = 10
var answer = 10
for _ in 1...power {
answer *= base
}
//使用半開區間運算子(..<)來表示一個左閉右開的區間
let minutes = 60
for tickMark in 0..<minutes {
// 每1分鐘呈現一個刻度線(60次
print("tickMark: \(tickMark)")
}
//可以每5分鐘作為一個刻度。使用 stride(from:to:by:) 函式跳過不需要的標記。
let minuteInterval = 5
for tickMark in stride(from: 0, to: minutes, by: 5) {
// 每5分鐘呈現一個刻度線 (0, 5, 10, 15 ... 45, 50, 55)
print("tickMark: \(tickMark)")
}
//可以在閉區間使用 stride(from:through:by:) 起到同樣作用:
let hours = 12
let hourInterval = 3
for tickMark in stride(from: 3, through: hours, by: hourInterval) {
// 每3小時呈現一個刻度線 (3, 6, 9, 12)
print("tickMark: \(tickMark)")
}
While
while迴圈會一直執行一段語句直到條件變成false。
Swift 提供兩種while
迴圈形式:
- while 迴圈,每次在迴圈開始時計算條件是否符合;
- repeat-while 迴圈,每次在迴圈結束時計算條件是否符合。
While
//while condition {
// statements
//}
蛇和梯子(也叫做滑道和梯子)的小遊戲
let finalSquare = 25
var board = [Int](repeating:0, count:finalSquare + 1)
board[03] = +08; board[06] = +11; board[09] = +09;board[10] = +02;
board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08;
var square = 0
var diceRoll = 0
while square < finalSquare {
//投骰子
diceRoll += 1
if diceRoll == 7 {diceRoll = 1}
//根據點數移動
square += diceRoll
if square < board.count {
//如果玩家還在棋盤上,順著梯子爬上去或者順著蛇滑下去
square += board[square]
}
}
print("Game over!")
Repeat-While
while迴圈的另外一種形式是repeat-while,它和while的區別是在判斷迴圈條件之前,先執行一次迴圈的程式碼塊。然後重複迴圈直到條件為false。
格式:
//repeat {
// statements
//} while condition
使用repeat-while迴圈來替代while迴圈。
board = [Int](repeating: 0, count: finalSquare + 1)
board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
square = 0
diceRoll = 0
repeat {
//順著梯子爬上去或者順著蛇滑下去
square += board[square]
//投骰子
diceRoll += 1
if diceRoll == 7 {
diceRoll = 1
}
//根據點數移動
square += diceRoll
} while square < finalSquare
print("Game over!")
條件語句
if
var temperatureInFahrenheit = 30
if temperatureInFahrenheit <= 32 {
print("It's very cold. Consider wearing a scarf.")
}
執行 else 語句
temperatureInFahrenheit = 40
if temperatureInFahrenheit <= 32 {
print("It's very cold. Consider wearing a scarf.")
} else {
print("It's not that cold. Wear a t-shirt.")
}
更多分支
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.")
}
temperatureInFahrenheit = 72
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.")
}
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
//}
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")
}
與 C 和 Objective-C 中的switch語句不同,在 Swift 中,當匹配的 case 分支中的程式碼執行完畢後,程式會終止switch語句,而不會繼續執行下一個 case 分支。
//每一個 case 分支都必須包含至少一條語句。像下面這樣書寫程式碼是無效的,因為第一個 case 分支是空的:
let anotherCharacter: Character = "a"
switch anotherCharacter {
//case "a"://無效,這個分支沒有下面沒有語句 每一個 case 分支都必須包含至少一條語句 error
case "A":
print("The letter A")
default:
print("Not the letter A")
}
//為了讓單個case同時匹配a和A,可以將這個兩個值組合成一個複合匹配,並且用逗號分開:
switch anotherCharacter {
case "a", "A":
print("The letter A")
default:
print("Not the letter A")
}
如果想要顯式貫穿case分支,請使用fallthrough語句,詳情請參考貫穿
區間匹配
//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"
}
//元組
//元組中的元素可以是值,也可以是區間。另外,使用下劃線(_)來匹配所有可能的值。
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")
}
值繫結 (Value Bindings)
//case 分支允許將匹配的值繫結到一個臨時的常量或變數,並且在case分支體內使用 —— 這種行為被稱為值繫結(value binding),因為匹配的值在case分支體內,與臨時的常量或變數繫結。
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("somewherr else at (\(x), \(y)")
}
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")
}
複合匹配
//可以將這幾種可能放在同一個case後面,並且用逗號隔開
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")
}
let stillAnotherPoint = (9, 0)
switch stillAnotherPoint {
case (let distance, 0), (0, let distance):
print("On an axis, \(distance) from the origin")
default:
print("Not on an axis")
}
控制轉移語句
- continue 語句告訴一個迴圈體立刻停止本次迴圈,重新開始下次迴圈。就好像在說“本次迴圈我已經執行完了”,但是並不會離開整個迴圈體。
- break語句會立刻結束整個控制流的執行。當你想要更早的結束一個switch程式碼塊或者一個迴圈體時,你都可以使用break語句
- fallthrough 如果你確實需要 C 風格的貫穿的特性,你可以在每個需要該特性的 case 分支中使用fallthrough關鍵字。
- return
- throw
continue
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)
break
break語句會立刻結束整個控制流的執行。break 可以在 switch 或迴圈語句中使用,用來提前結束switch或迴圈語句。
let numberSymbol: Character = "三" // 簡體中文裡的數字 3
var possibleIntegerValue: Int?
switch numberSymbol {
case "1", "١", "一", "๑":
possibleIntegerValue = 1
case "2", "٢", "二", "๒":
possibleIntegerValue = 2
case "3", "٣", "三", "๓":
possibleIntegerValue = 3
case "4", "٤", "四", "๔":
possibleIntegerValue = 4
default:
break
}
if let integerValue = possibleIntegerValue {
print("The integer value of \(numberSymbol) is \(integerValue).")
} else {
print("An integer value could not be found for \(numberSymbol).")
}
fallthrough
在 Swift 裡,switch語句不會從上一個 case 分支跳轉到下一個 case 分支中。相反,只要第一個匹配到的 case 分支完成了它需要執行的語句,整個switch程式碼塊完成了它的執行。
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)
帶標籤的語句
可以使用標籤(statement label)來標記一個迴圈體或者條件語句,對於一個條件語句,你可以使用break加標籤的方式,來結束這個被標記的語句。
//同樣的規則適用於所有的迴圈體和條件語句。
//label name:while condition {statements}
board = [Int](repeating:0, count:finalSquare + 1)
board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
square = 0
diceRoll = 0
//label
gameLoop: while square != finalSquare {
diceRoll += 1
if diceRoll == 7 {
diceRoll = 1
}
switch square + diceRoll {
case finalSquare:
//骰子數剛好使玩家移動到最終的方格里,遊戲結束
break gameLoop //沒有gameLoop將中斷switch而不是while
case let newSquare where newSquare > finalSquare:
//骰子數將會使玩家的移動超出最後的方格,那麼這種移動是不合法的,玩家需要重新投骰子
continue gameLoop //只有一個迴圈,可省略gameLoop
default:
//合法移動,做正常的處理
square += diceRoll
square += board[square]
}
}
print("Gamen over")
提前退出
//像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(person: ["name" : "John"])
greet(person: ["name": "Jane", "location": "Cupertino"])
檢測API可用性
//我們在if或guard語句中使用可用性條件(availability condition)去有條件的執行一段程式碼,來在執行時判斷呼叫的API是否可用。編譯器使用從可用性條件語句中獲取的資訊去驗證,在這個程式碼塊中呼叫的 API 是否可用。
//平臺名字可以是iOS,macOS,watchOS和tvOS
//if #available(platform name version, ..., *) {
// APIs 可用,語句將執行
//} else {
// APIs 不可用,語句將不執行
//}
if #available(iOS 10, macOS 10.12, *) {
// 在 iOS 使用 iOS 10 的 API, 在 macOS 使用 macOS 10.12 的 API
} else {
// 使用先前版本的 iOS 和 macOS 的 API
}
相關文章
- Swift-控制流(Control Flow)Swift
- Control Flow 控制流程
- JavaScript statement flow control || JavaScript 語句流程控制JavaScript
- Chapter2:Asynchronous Control Flow PatternsAPT
- STREAM的CAPTURE出現PAUSED FOR FLOW CONTROLAPT
- Git-flow 工作流使用Git
- Swift--基本運算子Swift
- GitLab、Git Flow 工作流使用Gitlab
- 《Windows 10 Control Flow Guard Internals》 Reading NotesWindows
- CSAPP英語學習系列:Chapter 8: Exceptional Control FlowAPPAPTException
- streams capture狀態PAUSED FOR FLOW CONTROL原因分析和診斷APT
- Flutter 佈局控制元件篇-->Wrap、FlowFlutter控制元件
- 控制檔案-control file
- control file(控制檔案)
- goim 中的 data flow 資料流轉及思考Go
- ORA-25307 ENQUEUE RATE TOO HIGH. ENABLE FLOW CONTROLENQ
- SAP SD基礎知識之憑證流(Document Flow)
- 實戰 | 使用 Kotlin Flow 構建資料流 "管道"Kotlin
- (二)Flutter學習之Dart展開操作符 和 Control Flow CollectionsFlutterDart
- [翻譯] TensorFlow 分散式之論文篇 "Implementation of Control Flow in TensorFlow"分散式
- python控制流Python
- SOLIDWORKS Flow Simulation軟體流體分析結果檢視Solid
- ORACLE 控制檔案(Control Files)概述Oracle
- 重建控制檔案 recreate control file
- MySQL 控制流函式MySql函式
- JavaScript程式控制流(轉)JavaScript
- Swift 新特性 – 訪問控制(Access Control)Swift
- 細水長flow之NICE:流模型的基本概念與實現模型
- Java™ 教程(控制流語句)Java
- Promise非同步控制流模式Promise非同步模式
- ?年學 go 2:控制流Go
- Laravel Inversion of Control (控制反轉) 概念簡介Laravel
- Oracle Control File(控制檔案)的內容Oracle
- Oracle 快照控制檔案(snapshot control file)Oracle
- Oracle快照控制檔案(snapshot control file)Oracle
- Spring系列學習之Spring Cloud Data Flow 微服務資料流SpringCloud微服務
- [SceneKit專題]14-Motion-Control運動控制
- 【翻譯】控制檔案管理(Managing Control Files)