Swift-控制流

1. For in 循環(huán)

遍歷一個(gè)集合中的所有元素匀们。 例如:數(shù)組中的元素惭载、范圍內(nèi)的數(shù)字或者字符串中的字符旱函。

  • 遍歷一個(gè)數(shù)組所有元素:
let names = ["Anna", "Alex", "Brian", "Jack"]
for name in names {
    print("Hello, \(name)!")
}
// Hello, Anna!
// Hello, Alex!
// Hello, Brian!
// Hello, Jack!
  • 遍歷一個(gè)字典來(lái)訪問(wèn)它的鍵值對(duì):
let numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
for (animalName, legCount) in numberOfLegs {
    print("\(animalName)s have \(legCount) legs")
}
// cats have 4 legs
// ants have 6 legs
// spiders have 8 legs
  • 遍歷數(shù)字范圍
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
  • 不需要區(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”
  • 使用半開(kāi)區(qū)間運(yùn)算符(..<)來(lái)表示一個(gè)左閉右開(kāi)的區(qū)間:
let minutes = 60
for tickMark in 0..<minutes {
    // 每一分鐘都渲染一個(gè)刻度線(60次)
}
  • 可以每 5 分鐘作為一個(gè)刻度描滔。使用 stride(from:to:by:) 函數(shù)跳過(guò)不需要的標(biāo)記:
let minuteInterval = 5
let minutes = 60
for tickMark in stride(from: 0, to: minutes, by: minuteInterval) {
    // 每5分鐘渲染一個(gè)刻度線(0, 5, 10, 15 ... 45, 50, 55)
}
  • 在閉區(qū)間使用 stride(from:through:by:) 起到同樣作用:
let hours = 12
let hourInterval = 3
for tickMark in stride(from: 3, through: hours, by: hourInterval) {
    // 每3小時(shí)渲染一個(gè)刻度線(3, 6, 9, 12)
}

2. While 循環(huán)

while 循環(huán)會(huì)一直運(yùn)行一段語(yǔ)句直到條件變成 false棒妨。Swift 提供兩種 while 循環(huán)形式:

  • while 循環(huán),每次在循環(huán)開(kāi)始時(shí)計(jì)算條件是否符合。
  • repeat-while 循環(huán)券腔,每次在循環(huán)結(jié)束時(shí)計(jì)算條件是否符合伏穆。

2.1 While

  • while 循環(huán)從計(jì)算一個(gè)條件開(kāi)始。如果條件為 true纷纫,會(huì)重復(fù)運(yùn)行一段語(yǔ)句枕扫,直到條件變?yōu)?false。
  • while 循環(huán)的一般格式:
while condition {
    statements
}

2.2 Repeat-While

  • 判斷循環(huán)條件之前辱魁,先執(zhí)行一次循環(huán)的代碼塊烟瞧。然后重復(fù)循環(huán)直到條件為 false。
  • repeat-while 循環(huán)的一般格式:
repeat {
    statements
} while condition

3. 條件語(yǔ)句

3.1 if

  • 該條件為 true 時(shí)染簇,才執(zhí)行相關(guān)代碼:
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.")
}   // 輸出“It's not that cold. Wear a t-shirt.”
  • 可以把多個(gè) if 語(yǔ)句鏈接在一起参滴,來(lái)實(shí)現(xiàn)更多分支:
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.")
}   // 輸出“It's really warm. Don't forget to wear sunscreen.”
  • 不需要完整判斷情況的時(shí)候,最后的 else 語(yǔ)句是可選的:
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.")
}

3.2 Switch

switch 語(yǔ)句會(huì)嘗試把某個(gè)值與若干個(gè)模式(pattern)進(jìn)行匹配锻弓。

3.2.1 不存在隱式的貫穿

與 C 和 Objective-C 中的 switch 語(yǔ)句不同砾赔,在 Swift 中,當(dāng)匹配的 case 分支中的代碼執(zhí)行完畢后青灼,程序會(huì)終止 switch 語(yǔ)句暴心,而不會(huì)繼續(xù)執(zhí)行下一個(gè) case 分支。

  • 把某個(gè)值與一個(gè)或若干個(gè)相同類型的值作比較:
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”
  1. Swift 中 break 不是必須的聚至。
  2. 在 Swift 中酷勺,當(dāng)匹配的 case 分支中的代碼執(zhí)行完畢后,程序會(huì)終止 switch 語(yǔ)句扳躬,而不會(huì)繼續(xù)執(zhí)行下一個(gè) case 分支脆诉。這也就是說(shuō),不需要在 case 分支中顯式地使用 break 語(yǔ)句贷币。
  • 每一個(gè) case 分支都必須包含至少一條語(yǔ)句:
let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a": // 無(wú)效击胜,這個(gè)分支下面沒(méi)有語(yǔ)句
case "A":
    print("The letter A")
default:
    print("Not the letter A")
}   
!R畚啤偶摔!這段代碼會(huì)報(bào)編譯錯(cuò)誤
  • 讓單個(gè) case 同時(shí)匹配 a 和 A,可以將這個(gè)兩個(gè)值組合成一個(gè)復(fù)合匹配促脉,并且用逗號(hào)分開(kāi):
let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a", "A":
    print("The letter A")
default:
    print("Not the letter A")
}   // 輸出“The letter A”

3.2.2 區(qū)間匹配

  • case 分支的模式也可以是一個(gè)值的區(qū)間
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.”

3.2.3 元組匹配

  • 可以使用元組在同一個(gè) switch 語(yǔ)句中測(cè)試多個(gè)值辰斋。
  • 元組中的元素可以是值,也可以是區(qū)間瘸味。
  • 使用下劃線(_)來(lái)匹配所有可能的值宫仗。
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”

Swift 允許多個(gè) case 匹配同一個(gè)值。
在這個(gè)例子中旁仿,點(diǎn) (0, 0)可以匹配所有四個(gè) case藕夫。
如果存在多個(gè)匹配,那么只會(huì)執(zhí)行第一個(gè)被匹配到的 case 分支。
點(diǎn) (0, 0)會(huì)首先匹配 case (0, 0)毅贮,因此剩下的能夠匹配的分支都會(huì)被忽視掉办悟。

3.2.4 值綁定(Value Bindings)

case 分支允許將匹配的值聲明為臨時(shí)常量或變量,并且在 case 分支體內(nèi)使用 —— 這種行為被稱為值綁定(value binding)滩褥,因?yàn)槠ヅ涞闹翟?case 分支體內(nèi)病蛉,與臨時(shí)的常量或變量綁定。

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”
注意:
    這個(gè) switch 語(yǔ)句不包含默認(rèn)分支铸题。這是因?yàn)樽詈笠粋€(gè) case ——case let(x, y) 聲明了一個(gè)可以匹配余下所有值的元組铡恕。這使得 switch 語(yǔ)句已經(jīng)完備了,因此不需要再書(shū)寫(xiě)默認(rèn)分支丢间。

3.2.5 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”

3.2.6 復(fù)合型 Cases

  • 當(dāng)多個(gè)條件可以使用同一種方法來(lái)處理時(shí),可以將這幾種可能放在同一個(gè) case 后面烘挫,并且用逗號(hào)隔開(kāi)诀艰。當(dāng) case 后面的任意一種模式匹配的時(shí)候,這條分支就會(huì)被匹配饮六。并且其垄,如果匹配列表過(guò)長(zhǎng),還可以分行書(shū)寫(xiě):
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”
  • 復(fù)合匹配同樣可以包含值綁定卤橄。復(fù)合匹配里所有的匹配模式绿满,都必須包含相同的值綁定。并且每一個(gè)綁定都必須獲取到相同類型的值窟扑。 這保證了喇颁,無(wú)論復(fù)合匹配中的哪個(gè)模式發(fā)生了匹配,分支體內(nèi)的代碼嚎货,都能獲取到綁定的值橘霎,并且綁定的值都有一樣的類型。
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")
}   // 輸出“On an axis, 9 from the origin”

上面的 case 有兩個(gè)模式:

  1. (let distance, 0) 匹配了在 x 軸上的值殖属,
  2. (0, let distance) 匹配了在 y 軸上的值姐叁。

兩個(gè)模式都綁定了 distance,并且 distance 在兩種模式下洗显,都是整型——這意味著分支體內(nèi)的代碼外潜,只要 case 匹配,都可以獲取到 distance 值挠唆。

4. 控制轉(zhuǎn)移語(yǔ)句

控制轉(zhuǎn)移語(yǔ)句改變你代碼的執(zhí)行順序橡卤,通過(guò)它可以實(shí)現(xiàn)代碼的跳轉(zhuǎn)。

4.1Swift 有五種控制轉(zhuǎn)移語(yǔ)句:

  • continue:告訴一個(gè)循環(huán)體立刻停止本次循環(huán)损搬,重新開(kāi)始下次循環(huán)。
  • break:break 語(yǔ)句會(huì)立刻結(jié)束整個(gè)控制流的執(zhí)行。break 可以在 switch 或循環(huán)語(yǔ)句中使用巧勤,用來(lái)提前結(jié)束 switch 或循環(huán)語(yǔ)句嵌灰。
  • fallthrough:貫穿(Fallthrough)從上一個(gè) case 分支跳轉(zhuǎn)到下一個(gè) case 分支中。
  • return:返回
  • throw:錯(cuò)誤拋出
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.”

4.2 帶標(biāo)簽的語(yǔ)句

標(biāo)簽(statement label):標(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í)行延曙。
  • 針對(duì) while 循環(huán)體的標(biāo)簽語(yǔ)法豌鹤,同樣的規(guī)則適用于所有的循環(huán)體和條件語(yǔ)句:
label name: while condition {
     statements
 }

4.3 提前退出

  • 使用 guard 語(yǔ)句來(lái)要求條件必須為真時(shí),以執(zhí)行 guard 語(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(person: ["name": "John"])
// 輸出“Hello John!”
// 輸出“I hope the weather is nice near you.”
greet(person: ["name": "Jane", "location": "Cupertino"])
// 輸出“Hello Jane!”
// 輸出“I hope the weather is nice in Cupertino.”
注意:
    1.如果條件不被滿足灵临,在 else 分支上的代碼就會(huì)被執(zhí)行。
    2.這個(gè)分支必須轉(zhuǎn)移控制以退出 guard 語(yǔ)句出現(xiàn)的代碼段趴荸。
    3.可以用控制轉(zhuǎn)移語(yǔ)句如 return儒溉、break、continue 或者 throw 做這件事发钝,或者調(diào)用一個(gè)不返回的方法或函數(shù)顿涣,例如 fatalError()。

相比于可以實(shí)現(xiàn)同樣功能的 if 語(yǔ)句笼平,按需使用 guard 語(yǔ)句會(huì)提升我們代碼的可讀性园骆。它可以使你的代碼連貫的被執(zhí)行而不需要將它包在 else 塊中,它可以使你在緊鄰條件判斷的地方寓调,處理違規(guī)的情況锌唾。

4.4 檢測(cè) API 可用性

  • Swift 內(nèi)置支持檢查 API 可用性,這可以確保我們不會(huì)在當(dāng)前部署機(jī)器上夺英,不小心地使用了不可用的 API晌涕。
  • 編譯器使用 SDK 中的可用信息來(lái)驗(yàn)證我們的代碼中使用的所有 API 在項(xiàng)目指定的部署目標(biāo)上是否可用。如果我們嘗試使用一個(gè)不可用的 API痛悯,Swift 會(huì)在編譯時(shí)報(bào)錯(cuò)余黎。
if #available(iOS 10, macOS 10.12, *) {
    // 在 iOS 使用 iOS 10 的 API, 在 macOS 使用 macOS 10.12 的 API
} else {
    // 使用先前版本的 iOS 和 macOS 的 API
}
  • 平臺(tái)名字可以是:iOS,macOS载萌,watchOS 和 tvOS
if #available(平臺(tái)名稱 版本號(hào), ..., *) {
    APIs 可用惧财,語(yǔ)句將執(zhí)行
} else {
    APIs 不可用巡扇,語(yǔ)句將不執(zhí)行
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市垮衷,隨后出現(xiàn)的幾起案子厅翔,更是在濱河造成了極大的恐慌,老刑警劉巖搀突,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件刀闷,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡仰迁,警方通過(guò)查閱死者的電腦和手機(jī)甸昏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)徐许,“玉大人施蜜,你說(shuō)我怎么就攤上這事“硌埃” “怎么了花墩?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)澄步。 經(jīng)常有香客問(wèn)我冰蘑,道長(zhǎng),這世上最難降的妖魔是什么村缸? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任祠肥,我火速辦了婚禮,結(jié)果婚禮上梯皿,老公的妹妹穿的比我還像新娘仇箱。我一直安慰自己,他們只是感情好东羹,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布剂桥。 她就那樣靜靜地躺著,像睡著了一般属提。 火紅的嫁衣襯著肌膚如雪权逗。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天冤议,我揣著相機(jī)與錄音斟薇,去河邊找鬼。 笑死恕酸,一個(gè)胖子當(dāng)著我的面吹牛堪滨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蕊温,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼袱箱,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼遏乔!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起发笔,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤按灶,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后筐咧,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體畦戒,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡肩钠,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了卖氨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片艇挨。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡残炮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出缩滨,到底是詐尸還是另有隱情势就,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布脉漏,位于F島的核電站苞冯,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏侧巨。R本人自食惡果不足惜舅锄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望司忱。 院中可真熱鬧皇忿,春花似錦、人聲如沸坦仍。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)繁扎。三九已至幔荒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間锻离,已是汗流浹背铺峭。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留汽纠,地道東北人卫键。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像虱朵,于是被迫代替她去往敵國(guó)和親莉炉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子钓账,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Swift 提供了類似 C 語(yǔ)言的流程控制結(jié)構(gòu),包括可以多次執(zhí)行任務(wù)的for和while循環(huán)絮宁,基于特定條件選擇執(zhí)行...
    窮人家的孩紙閱讀 690評(píng)論 1 1
  • Swift提供了多種控制流聲明梆暮。包括while循環(huán)來(lái)多次執(zhí)行一個(gè)任務(wù);if绍昂,guard和switch聲明來(lái)根據(jù)確定...
    BoomLee閱讀 1,936評(píng)論 0 3
  • Swift提供了多種流程控制結(jié)構(gòu)啦粹,包括可以多次執(zhí)行任務(wù)的while循環(huán),基于特定條件選擇執(zhí)行不同代碼分支的if窘游、g...
    CDLOG閱讀 708評(píng)論 0 1
  • Swift提供了各種控制流語(yǔ)句唠椭。 這些包括while循環(huán)來(lái)執(zhí)行多次任務(wù); if,guard和switch語(yǔ)句忍饰,以根...
    Joker_King閱讀 416評(píng)論 0 0
  • Swift提供了多種流程控制結(jié)構(gòu)贪嫂,包括可以多次執(zhí)行任務(wù)的while循環(huán),基于特定條件基于特定條件選擇執(zhí)行不同代碼分...
    edison0428閱讀 1,235評(píng)論 0 0