Flow Control(控制流)

// 控制流
// “包括可以多次執(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í)行")
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市寿桨,隨后出現(xiàn)的幾起案子此衅,更是在濱河造成了極大的恐慌,老刑警劉巖亭螟,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件挡鞍,死亡現(xiàn)場離奇詭異,居然都是意外死亡预烙,警方通過查閱死者的電腦和手機墨微,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來默伍,“玉大人欢嘿,你說我怎么就攤上這事∫埠” “怎么了炼蹦?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長狸剃。 經(jīng)常有香客問我掐隐,道長,這世上最難降的妖魔是什么钞馁? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任虑省,我火速辦了婚禮,結(jié)果婚禮上僧凰,老公的妹妹穿的比我還像新娘探颈。我一直安慰自己,他們只是感情好训措,可當(dāng)我...
    茶點故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布伪节。 她就那樣靜靜地躺著,像睡著了一般绩鸣。 火紅的嫁衣襯著肌膚如雪怀大。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天呀闻,我揣著相機與錄音化借,去河邊找鬼。 笑死捡多,一個胖子當(dāng)著我的面吹牛蓖康,可吹牛的內(nèi)容都是我干的铐炫。 我是一名探鬼主播,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼钓瞭,長吁一口氣:“原來是場噩夢啊……” “哼驳遵!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起山涡,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤堤结,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后鸭丛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體竞穷,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年鳞溉,在試婚紗的時候發(fā)現(xiàn)自己被綠了瘾带。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,110評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡熟菲,死狀恐怖看政,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情抄罕,我是刑警寧澤允蚣,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站呆贿,受9級特大地震影響嚷兔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜做入,卻給世界環(huán)境...
    茶點故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一冒晰、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧竟块,春花似錦壶运、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至秫逝,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間询枚,已是汗流浹背违帆。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留金蜀,地道東北人刷后。 一個月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓的畴,卻偏偏與公主長得像,于是被迫代替她去往敵國和親尝胆。 傳聞我的和親對象是個殘疾皇子丧裁,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,047評論 2 355

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