// 控制流
// “包括可以多次執(zhí)行任務(wù)的while循環(huán)吞彤,基于特定條件選擇執(zhí)行不同代碼分支的if漾稀、guard和switch語句买鸽,還有控制流程跳轉(zhuǎn)到其他代碼位置的break和continue語句查剖。”
//“Swift 還提供了for-in循環(huán)鞭光,用來更簡單地遍歷數(shù)組(array)吏廉,字典(dictionary),區(qū)間(range)惰许,字符串(string)和其他序列類型席覆。”
//1. for-in
// for-in可以遍歷collection中的所有元素汹买,數(shù)組或者字典都可以遍歷佩伤。
for index in 1...5{
print("index is \(index)")
}
//“如果你不需要區(qū)間序列內(nèi)每一項的值,你可以使用下劃線(_)替代變量名來忽略這個值”
for _ in 1...5{
print("不需要值")
}
//2. while循環(huán)
// “while循環(huán)會一直運行一段語句直到條件變成false晦毙。 這類循環(huán)適合使用在第一次迭代前生巡,迭代次數(shù)未知的情況下
//“while循環(huán),每次在循環(huán)開始時計算條件是否符合见妒;
//repeat-while循環(huán)孤荣,每次在循環(huán)結(jié)束時計算條件是否符合,會至少執(zhí)行一次。
//2.1: “while循環(huán)從計算一個條件開始垃环。如果條件為true邀层,會重復(fù)運行一段語句,直到條件變?yōu)閒alse遂庄×仍海”
var i = 1
while i<5 {
i+=1
}
//2.2:“while循環(huán)的另外一種形式是repeat-while,它和while的區(qū)別是在判斷循環(huán)條件之前涛目,先執(zhí)行一次循環(huán)的代碼塊秸谢。然后重復(fù)循環(huán)直到條件為false∨危”
//“Swift語言的repeat-while循環(huán)和其他語言中的do-while循環(huán)是類似的”
repeat {
i+=1
}while i<10
//3. 條件語句
//3.1: “if語句最簡單的形式就是只包含一個條件估蹄,只有該條件為true時,才執(zhí)行相關(guān)代碼”
if i>5 {
print("jack")
}
//“if語句允許二選一執(zhí)行沫换,叫做else從句”
if i<5 {
print("rose")
}else{
print("jack")
}
//“多個if語句鏈接在一起臭蚁,來實現(xiàn)更多分支”
if i<5 {
print("rose")
}else if i<8 {
print("rose")
}else{
print("jack")
}
//“當(dāng)不需要完整判斷情況的時候,最后的else語句是可選的”
if i < 5 {
print("rose")
}else if i < 8 {
print("rose")
}
//3.2: “switch語句會嘗試把某個值與若干個模式(pattern)進行匹配讯赏。根據(jù)第一個匹配成功的模式垮兑,switch語句會執(zhí)行對應(yīng)的代碼。當(dāng)有可能的情況較多時漱挎,通常用switch語句替換if語句”
//“switch語句由多個 case 構(gòu)成系枪,每個由case關(guān)鍵字開始。為了匹配某些更特定的值磕谅,Swift 提供了幾種方法來進行更復(fù)雜的模式匹配私爷,這些模式將在本節(jié)的稍后部分提到”
//“switch語句必須是完備的。這就是說膊夹,每一個可能的值都必須至少有一個 case 分支與之對應(yīng)衬浑。在某些不可能涵蓋所有值的情況下,你可以使用默認(rèn)(default)分支來涵蓋其它所有沒有對應(yīng)的值割疾,這個默認(rèn)分支必須在switch語句的最后面嚎卫。”
let someCharacter: Character = "z"
switch someCharacter {
case "a":
print("the first leter of the alphabet")
case "z":
print("the last letter of the alphabet")
default:
print("some other character")
}
// 不存在隱式的貫穿
//“與 C 和 Objective-C 中的switch語句不同宏榕,在 Swift 中拓诸,當(dāng)匹配的 case 分支中的代碼執(zhí)行完畢后,程序會終止switch語句麻昼,而不會繼續(xù)執(zhí)行下一個 case 分支奠支。這也就是說,不需要在 case 分支中顯式地使用break語句”
//注意:雖然在Swift中break不是必須的抚芦,但你依然可以在 case 分支中的代碼執(zhí)行完畢前使用break跳出”
//“每一個 case 分支都必須包含至少一條語句倍谜。像下面這樣書寫代碼是無效的迈螟,因為第一個 case 分支是空的:”
//let anotherCharacter: Character = "a"
//switch anotherCharacter {
//case "a":
//case "A":
// print("letter A")
//default:
// print("Not the letter A")
//}
//“不像 C 語言里的switch語句,在 Swift 中尔崔,switch語句不會一起匹配"a"和"A"答毫。相反的,上面的代碼會引起編譯期錯誤:case "a": 不包含任何可執(zhí)行語句”
//“可以將這個兩個值組合成一個復(fù)合匹配季春,并且用逗號分開:”
let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a","A":
print("letter a")
default:
print("no letter a")
}
//區(qū)間匹配
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"
default:
naturalCount = "many"
}
print(naturalCount)
//switch與元組
//“我們可以使用元組在同一個switch語句中測試多個值洗搂。元組中的元素可以是值,也可以是區(qū)間载弄。另外耘拇,使用下劃線(_)來匹配所有可能的值”
let somePoint = (1,1)
switch somePoint {
case (0,0):
print("0,0 is at the origin")
case (_,0):
print("somePoint,0 is on the x-axis")
case (0,_):
print("0,somePoint is on the y-axis")
case (-2...2,-2...2):
print("\(somePoint.0,somePoint.1) is inside of the box")
default:
print("is out side the box")
}
//“不像 C 語言,Swift 允許多個 case 匹配同一個值宇攻。實際上惫叛,在這個例子中,點(0, 0)可以匹配所有四個 case逞刷。但是嘉涌,如果存在多個匹配,那么只會執(zhí)行第一個被匹配到的 case 分支夸浅。
//switch與值綁定
//“case 分支允許將匹配的值綁定到一個臨時的常量或變量洛心,并且在case分支體內(nèi)使用 —— 這種行為被稱為值綁定(value binding),因為匹配的值在case分支體內(nèi)题篷,與臨時的常量或變量綁定”
let anotherPoint = (2,2)
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 an y value of \(y)")
case let (x,y):
print("some else at \(x,y)")
}
//“這個switch語句不包含默認(rèn)分支。這是因為最后一個 case ——case let(x, y)聲明了一個可以匹配余下所有值的元組厅目。這使得switch語句已經(jīng)完備了番枚,因此不需要再書寫默認(rèn)分支∷鸱螅”
//switch與where
//“case 分支的模式可以使用where語句來判斷額外的條件”
let yetAnothePoint = (1,-1)
switch yetAnothePoint {
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")
}
//switch與復(fù)合匹配
//“當(dāng)多個條件可以使用同一種方法來處理時葫笼,可以將這幾種可能放在同一個case后面,并且用逗號隔開拗馒。當(dāng)case后面的任意一種模式匹配的時候路星,這條分支就會被匹配。并且诱桂,如果匹配列表過長洋丐,還可以分行書寫”
let myCharacter: Character = "e"
switch myCharacter {
case "a","e","i","o","u":
print("\(someCharacter) is a vowel")
case "b","c","d","f","g","h","i","j",
"k","l" :
print("\(someCharacter) is a consonant")
default:
print("\(someCharacter) is not vowel or a consonant")
}
//“復(fù)合匹配同樣可以包含值綁定。復(fù)合匹配里所有的匹配模式挥等,都必須包含相同的值綁定友绝。并且每一個綁定都必須獲取到相同類型的值。這保證了肝劲,無論復(fù)合匹配中的哪個模式發(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")
}
//4. 控制轉(zhuǎn)移語句 ***
//“控制轉(zhuǎn)移語句改變你代碼的執(zhí)行順序掷漱,通過它可以實現(xiàn)代碼的跳轉(zhuǎn)粘室。Swift 有五種控制轉(zhuǎn)移語句:
/* continue
break
fallthrough
return
throw
*/
//4.1:“continue語句告訴一個循環(huán)體立刻停止本次循環(huán),重新開始下次循環(huán)卜范。就好像在說“本次循環(huán)我已經(jīng)執(zhí)行完了”衔统,但是并不會離開整個循環(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)
//4.2:“break語句會立刻結(jié)束整個控制流的執(zhí)行缰冤。當(dāng)你想要更早的結(jié)束一個switch代碼塊或者一個循環(huán)體時,你都可以使用break語句喳魏∶藿”
//“循環(huán)語句中的 break,當(dāng)在一個循環(huán)體中使用break時,會立刻中斷該循環(huán)體的執(zhí)行刺彩,然后跳轉(zhuǎn)到表示循環(huán)體結(jié)束的大括號(})后的第一行代碼迷郑。不會再有本次循環(huán)的代碼被執(zhí)行,也不會再有下次的循環(huán)產(chǎn)生创倔∥撕Γ”
for i in 1..<5 {
print(i)
if i>3 {
break
}
}
//“Switch 語句中的 break,當(dāng)在一個switch代碼塊中使用break時,會立即中斷該switch代碼塊的執(zhí)行畦攘,并且跳轉(zhuǎn)到表示switch代碼塊結(jié)束的大括號(})后的第一行代碼”
//“被用來匹配或者忽略一個或多個分支霸妹。因為 Swift 的switch需要包含所有的分支而且不允許有為空的分支,有時為了使你的意圖更明顯知押,需要特意匹配或者忽略某個分支叹螟。那么當(dāng)你想忽略某個分支時,可以在該分支內(nèi)寫上break語句台盯。當(dāng)那個分支被匹配到時罢绽,分支內(nèi)的break語句立即結(jié)束switch代碼塊”
let numberSymbol: Character = "二"
var possibleIntegerValue : Int?
switch numberSymbol {
case "1","一","n":
possibleIntegerValue = 1
case "2","二","e","n":
possibleIntegerValue = 2
case "3","s","三","j":
break
default:
break
}
if let integerValue = possibleIntegerValue {
print("the integer value of \(numberSymbol) is \(integerValue) ")
}else{
print("an integer value could not be found")
}
//“在上面的例子中,想要把Character所有的的可能性都枚舉出來是不現(xiàn)實的静盅,所以使用default分支來包含所有上面沒有匹配到字符的情況”
//4.3:貫穿 “Swift中的switch不會從上一個 case 分支落入到下一個 case 分支中良价。只要第一個匹配到的 case 分支完成了它需要執(zhí)行的語句,整個switch代碼塊完成了它的執(zhí)行”“相比之下蒿叠,C 語言要求你顯式地插入break語句到每個 case 分支的末尾來阻止自動落入到下一個 case 分支中”
//“如果你確實需要 C 風(fēng)格的貫穿的特性明垢,你可以在每個需要該特性的 case 分支中使用fallthrough關(guān)鍵字”
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)鍵字來“貫穿”到default分支中”
//注意:fallthrough關(guān)鍵字不會檢查它下一個將會落入執(zhí)行的 case 中的匹配條件。fallthrough簡單地使代碼繼續(xù)連接到下一個 case 中的代碼栈虚,這和 C 語言標(biāo)準(zhǔn)中的switch語句特性是一樣的袖外。
//4.4 帶標(biāo)簽的語句
//“在 Swift 中,你可以在循環(huán)體和條件語句中嵌套循環(huán)體和條件語句來創(chuàng)造復(fù)雜的控制流結(jié)構(gòu)魂务。并且曼验,循環(huán)體和條件語句都可以使用break語句來提前結(jié)束整個代碼塊泌射。因此,顯式地指明break語句想要終止的是哪個循環(huán)體或者條件語句鬓照,會很有用熔酷。類似地,如果你有許多嵌套的循環(huán)體豺裆,顯式指明continue語句想要影響哪一個循環(huán)體也會非常有用拒秘。”
//“你可以使用標(biāo)簽(statement label)來標(biāo)記一個循環(huán)體或者條件語句臭猜,對于一個條件語句躺酒,你可以使用break加標(biāo)簽的方式,來結(jié)束這個被標(biāo)記的語句蔑歌。對于一個循環(huán)語句羹应,你可以使用break或者continue加標(biāo)簽,來結(jié)束或者繼續(xù)這條被標(biāo)記語句的執(zhí)行”
for i in 1...10 {
for j in 1...10 {
if j>2 {
print("i:\(i),j:\(j)")
break //影響內(nèi)循環(huán)
}
}
if i>4 {
print("外循環(huán)i:\(i)")
break // 影響外循環(huán)
}
}
outLoop: for i in 1...10 {
insideLoop: for j in 1...10 {
if j>2 {
print("insieLoop: i:\(i),j:\(j)")
break insideLoop
}
}
if i>4 {
print("outLoop: i:\(i)")
break outLoop
}
}
//使用循環(huán)標(biāo)簽會讓層級更明顯次屠。
//5. 提前退出
//“像if語句一樣园匹,guard的執(zhí)行取決于一個表達式的布爾值。我們可以使用guard語句來要求條件必須為真時劫灶,以執(zhí)行g(shù)uard語句后的代碼裸违。不同于if語句,一個guard語句總是有一個else從句本昏,如果條件不為真則執(zhí)行else從句中的代碼”
func greet(_ peason : [ String : String ] ){
guard let name = peason["name"] else {
return
}
print("hello \(name)")
guard let location = peason["location"] else {
print("i hope the weather is nice in near you")
return
}
print("i hope the weather is nice in \(location)")
}
greet(["name":"jack"])
//hello jack
//i hope the weather is nice in near you
greet(["name":"rose","location":"Cupertino"])
//hello rose
//i hope the weather is nice in Cupertino
//“如果guard語句的條件被滿足供汛,則繼續(xù)執(zhí)行g(shù)uard語句大括號 后 的代碼。將變量或者常量的可選綁定作為guard語句的條件涌穆,都可以保護guard語句后面的代碼紊馏。“如果條件不被滿足蒲犬,在else分支上的代碼就會被執(zhí)行。這個分支必須轉(zhuǎn)移控制以退出guard語句出現(xiàn)的代碼段”“它可以用控制轉(zhuǎn)移語句如return,break,continue或者throw做這件事岸啡,或者調(diào)用一個不返回的方法或函數(shù)原叮,例如fatalError()”
//“相比于可以實現(xiàn)同樣功能的if語句,按需使用guard語句會提升我們代碼的可讀性巡蘸。它可以使你的代碼連貫的被執(zhí)行而不需要將它包在else塊中奋隶,它可以使你在緊鄰條件判斷的地方,處理違規(guī)的情況悦荒∥ㄐ溃”
//guard蠻好用的。
//6. 檢測API的可用性
//“Swift內(nèi)置支持檢查 API 可用性搬味,這可以確保我們不會在當(dāng)前部署機器上境氢,不小心地使用了不可用的API蟀拷。”
if #available(iOS 10,macOS 10.12, watchOS 1.0,tvOS 1.0,*){
print("API可用萍聊,語句將執(zhí)行")
}else{
print("API不可用问芬,語句不會執(zhí)行")
}