Swift--控制流程

來源:互聯網
上載者:User

標籤:desc   ack   stride   not   value   存在   跳出迴圈   pil   cond   

Swift中提供了一系列的控流狀態,其中包括可以多次執行相同任務的while迴圈、根據不同的條件執行不同分支的if guard switch 等語句,以及例如用break和continue來選擇是否跳出迴圈執行其他的代碼。

 

Swift也提供對數組、字典、範圍、字串等快速遍曆的方法:for-in迴圈。

 

Swift中的swift語句比類似於c語言中的功能要強大一些,Case語句可以適合多種不同的類型,例如間隔匹配、元組、或者一個特殊的類型。在switch case中,匹配的值可以綁定到臨時常量或變數,在case的主體中使用,複雜的匹配條件可以用where子句表示。

 

1. for-in迴圈

可以用for-in來迴圈遍曆數組、字典、字串中的字元等。

let names = ["Anna", "Alex", "Brian", "Jack"]for name in names {    print("Hello, \(name)!")}// Hello, Anna!// Hello, Alex!// Hello, Brian!// Hello, Jack!

 你可以用for-in遍曆字典來擷取到字典中的索引值對。字典中的每個item以(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// spiders have 8 legs// cats have 4 legs

 字典中的元素是無序的,遍曆字典的資料不能保證是按順序來的。通常你按順序插入一個新的值,字典也不會按順序遍曆。

也可以用for-in迴圈來遍曆數值範圍。

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

 

遍曆的序列是一個從1到5的數字範圍,包括使用閉域運算子(…)。將索引值設定為range(1)中的第一個數字,並執行迴圈中的語句。在這種情況下,迴圈只包含一個語句,該語句從5倍的表中輸出當前索引值的條目。在執行語句之後,將更新index的值,以包含range(2)中的第二個值,以及列印(_:分隔字元:terminator:)函數再次調用。這個過程一直持續到到達距離的末端。

 

在上面的例子中,index是一個常量,它的值是在迴圈的每次迭代開始時自動化佈建的。因此,索引不需要在使用前聲明。它被隱式地聲明為簡單地由它包含在迴圈聲明中,而不需要一個let聲明關鍵字。

 

如果您不需要從序列中獲得每個值,則可以使用一個底線代替變數名來忽略值。

let base = 3let power = 10var answer = 1for _ in 1...power {    answer *= base}print("\(base) to the power of \(power) is \(answer)")// Prints "3 to the power of 10 is 59049"

 

在一些情況下,你可能不想要閉區間(包括兩邊的值)。考慮一下在錶盤上畫一分鐘的秒錶刻度值,如果想畫60下,需要從0開始,請用半開區別操作符(..<)--其中包含最小值,但是不包含最大值。

let minutes = 60for tickMark in 0..<minutes {    // render the tick mark each minute (60 times)}

 有些使用者想讓他們的介面用更少的刻度時,他們可能5秒刻度一次。用 stride(from:to:by:)的方法跳過不想要的刻度值。

let minuteInterval = 5for tickMark in stride(from: 0, to: minutes, by: minuteInterval) {    // render the tick mark every 5 minutes (0, 5, 10, 15 ... 45, 50, 55)}

 閉區間也可以用stride(from:through:by)來代替:

let hours = 12let hourInterval = 3for tickMark in stride(from: 3, through: hours, by: hourInterval) {    // render the tick mark every 3 hours (3, 6, 9, 12)}

 

2. While迴圈

While迴圈根據判斷是否滿足條件開始的,if這個條件滿足,就執行while內部代碼,知道它的條件不滿足。

while condition {    statements}

 

3.Rapeat-While迴圈

repeat-while迴圈是另外一種while迴圈的版本。在判斷條件是否滿足的情況下,先執行迴圈內的代碼,如果條件不滿足,就繼續迴圈,知道滿足條件為止跳出迴圈。

repeat {    statements} while condition

 

4.條件控制語句

對不同的條件執行不同的代碼是很常見的。當出現錯誤的時候你可能需要執行不同的代碼或者當一個值太高或者太低時展示一個提示資訊。要實現這樣的效果,讓你的部分代碼成為條件陳述式。

Swift提供兩種方法允許在代碼添加條件分支:if語句和switch語句。通常,你用if語句來判斷一個只有幾個可能的簡單判斷句;switch比較適合判斷一些值比較多的複雜條件,並且對匹配不同的條件選擇不同的執行代碼的情況中是非常有用的。

(1)if

在最近簡單的形式中,if語句只有一個簡單if條件。當條件為true時,會執行if內部的代碼。

var temperatureInFahrenheit = 30if temperatureInFahrenheit <= 32 {    print("It‘s very cold. Consider wearing a scarf.")}// Prints "It‘s very cold. Consider wearing a scarf."

if語句可以提供另一組語句,稱為else子句,用於條件為false的情況。這些語句由else關鍵字表示。

temperatureInFahrenheit = 40if temperatureInFahrenheit <= 32 {    print("It‘s very cold. Consider wearing a scarf.")} else {    print("It‘s not that cold. Wear a t-shirt.")}// Prints "It‘s not that cold. Wear a t-shirt."

 你可以將多個if語句疊加使用,可以考慮額外的字句;

temperatureInFahrenheit = 90if 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.")}// Prints "It‘s really warm. Don‘t forget to wear sunscreen."

 (2)switch

switch語句可以認為是一個值與多個可能值匹配的過程。當有一個值匹配成功後,就是執行對應的代碼塊switch為響應多個可選項的if語句提供另外一個選擇。

在swith簡單格式中,switch語句將一個值與相同類型的一個或多個值進行比較:

switch some value to consider {case value 1:    respond to value 1case value 2,     value 3:    respond to value 2 or 3default:    otherwise, do something else}

 

每個switch語句都是有多個case語句組成的,每個case語句以case 關鍵字開始。除了比較指定的值外,swift還為匹配複雜的case語句提供多種方法。

類似於if語句,每個case語句的分支由執行的代碼分割開。switch語句決定選擇哪個分支。

 

每個switch語句都應該是詳細的。每個可能值的類型都應該符合switch語句中其中一個case的類型。如果不適合為所有可能值提供一個case語句,你可以定一個default的語句去包含任何不明確的值。這個default語句以default關鍵字來聲明,而且必須出現在最後。

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")}// Prints "The last letter of the alphabet"

 

與c或者oc中的switch不一樣的是, 在swift中,switch語句不會自動進入下一個case語句中。相反,一旦switch語句符合某個case語句並執行完代碼後,不需要明確寫break,switch的case語句也會結束。相比於c中的switch語句更安全、更容易使用,而且容易避免錯誤。

 

每個case語句下都應有至少一句執行的代碼,如下的代碼就是無效,因為第一個case是空的:

let anotherCharacter: Character = "a"switch anotherCharacter {case "a": // Invalid, the case has an empty bodycase "A":    print("The letter A")default:    print("Not the letter A")}// This will report a compile-time error.

 與c語言的switch語句不一致,這個switch語句沒有同時滿足於“a”和“b”的情況。同時,它會在case“a”語句中會報一個編譯時間錯誤:case “a”沒有包含任何執行的代碼。這種方法避免了偶然從一個case條件,進入下一個條件的發生,以及讓代碼更加安全、意圖更加明確。

 

要實現一個符合“a”和“A”的case語句中,把兩個值結合在同一個複合的case語句中用“,”分隔開。

let anotherCharacter: Character = "a"switch anotherCharacter {case "a", "A":    print("The letter A")default:    print("Not the letter A")}// Prints "The letter A"

 為了便於閱讀,一個符合語句可以寫成多行。

 

(1)間隔匹配

swift 中case的值可以在間隔中檢查出來,如下的例子,這個例子使用數字間隔為任何大小的數字提供自然語言計數:

let approximateCount = 62let countedThings = "moons orbiting Saturn"let naturalCount: Stringswitch 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).")// Prints "There are dozens of moons orbiting Saturn."

 

(2)元組

你可以用元組來測試swith語句中的多個值是否相同。每個元組的的元素可是根據不同的值或者不同的間隔值來測試。或者你可以用“_”去匹配所有的可能值。

 

例如下面的例子,取(x, y)的點,用元組(Int, Int)類型表示:

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))")}// Prints "on the x-axis with an x value of 2"

 

(3)where

switch語句中可以用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")}// Prints "(1, -1) is on the line x == -y"

 

(4)複雜語句

switch多個case中如果case中的代碼是相同的,可以把兩個條件寫在同一個case語句中,每個條件用“,”號分割開。如果有任何的一個條件滿足就認為這個case條件滿足。如果這個條件陳述式太長,可以用多行顯示:

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")}// Prints "e is a vowel"

 switch語句的第一個例子與英語中的所有五個小寫母音匹配。同樣,它的第二種情況匹配所有小寫英語輔音。最後,預設情況匹配任何其他字元。

 

複合陳述式還可以包括值綁定。複合陳述式的所有模式都必須包含相同的值綁定集,而且每個綁定都必須從複合陳述式中的所有模式中獲得相同類型的值。這確保了,無論複合陳述式中的哪一部分匹配,case主體中的代碼始終可以訪問綁定的值,並且值始終具有相同的類型。

 

5. 控制轉移語句

控制轉移語句可以改變你代碼執行的順序,通過控制轉移語句從一個代碼塊到另個代碼塊。Swift有5個控制5個轉移語句:

contitue

break

fallthrough

return

throw

本章只介紹前面的三種控制轉移語句。

(1)continue

continue這個語句是告訴迴圈結束當前的代碼執行,重新開始下一個迴圈。相當於說:“一直在重複迴圈當前的迴圈”,沒有離開這個迴圈。

接下來的例子是,刪除一個小寫字串中的母音字母新成一個新的字串:

let puzzleInput = "great minds think alike"var puzzleOutput = ""let charactersToRemove: [Character] = ["a", "e", "i", "o", "u", " "]for character in puzzleInput {    if charactersToRemove.contains(character) {        continue    } else {        puzzleOutput.append(character)    }}print(puzzleOutput)// Prints "grtmndsthnklk"

 (2)break

break語句可以立刻結束執行的代碼塊。break語句可以用在switch或者迴圈語句內,當你想提前結束執行代碼的時候。

 

在迴圈語句中使用break

當你在迴圈語句中使用break時,break會立刻結束當前的迴圈代碼並跳出該迴圈從而執行“}”外的代碼。當前的迴圈代碼不再執行,也不會重新開始一輪新的迴圈。

 

在switch語句中用break

當break用在switch分支中時,break的使用可以立刻技術switch分支內的執行代碼,並且執行switch外及switch中“}”外的代碼。

這個行為可以在匹配或者忽略switch語句中用到。因為Swift中的swith語句是詳盡的而且在case語句中不允許有空的代碼塊,為了你的思路更清晰,有時候認真匹配或者忽略一些case語句是有必要的。當switch中的執行其中複合的case語句時,case語句如果有break,執行到break時那麼就會立刻結束當前switch代碼。

let numberSymbol: Character = "三"  // Chinese symbol for the number 3var possibleIntegerValue: Int?switch numberSymbol {case "1", "?", "一", "?":    possibleIntegerValue = 1case "2", "?", "二", "?":    possibleIntegerValue = 2case "3", "?", "三", "?":    possibleIntegerValue = 3case "4", "?", "四", "?":    possibleIntegerValue = 4default:    break}if let integerValue = possibleIntegerValue {    print("The integer value of \(numberSymbol) is \(integerValue).")} else {    print("An integer value could not be found for \(numberSymbol).")}// Prints "The integer value of 三 is 3."

 (3)fallthrough

在swift,swift語句中的每個case不會結束後自動進入下一個case語句判斷中,當有個case字句一旦滿足條件時這個switch語句就完全被執行了。與之相反的是,在c語言中明確指出需要,在case語句結束後插入break,防止從這個case語句中進入下一個case語句。避免預設執行fallthrough意味著swift中的switch語句比c中的更加一致和可預測性,從而可以避免錯誤地執行多個switch語句。

如果你需要c類型的fallthrough行為,你可以選擇在case與case之間用fallthrough關鍵字。

let integerToDescribe = 5var description = "The number \(integerToDescribe) is"switch integerToDescribe {case 2, 3, 5, 7, 11, 13, 17, 19:    description += " a prime number, and also"    fallthroughdefault:    description += " an integer."}print(description)// Prints "The number 5 is a prime number, and also an integer."

 注意:fallthrouht關鍵的使用時,不會判斷下一個case語句的條件,而是直接進入執行下一個case語句的代碼塊。

6.標籤聲明

在switf中,你可能在一個迴圈語句中嵌套一個迴圈和條件陳述式從而產生一個複雜的控制條件陳述式。然而迴圈和條件陳述式都可以用break來結束他們的執行。因此,有時候在迴圈語句中用break語句結束代碼是很有用的。同樣,如果有多個嵌套迴圈語句中,在迴圈語句中用continue 也是很有效。

 

為了達到這個目標,你可以用標籤語句來標記一個迴圈語句或者條件陳述式。使用條件陳述式,可以在語句標籤中使用break語句結束標記語句的執行。在迴圈語句中,你可以在標籤語句中用break或者continue語句去結束或者繼續標記語句的執行。

 

一個標籤語句的聲明格式如下:在語句前加上一個label的名字用“:”分隔開。

(label name): while condition {    statements}//()不用寫上,此處寫上為了提示這個一個整體的名字,並不是label + name

 例子如下:

gameLoop: while square != finalSquare {    diceRoll += 1    if diceRoll == 7 { diceRoll = 1 }    switch square + diceRoll {    case finalSquare:        // diceRoll will move us to the final square, so the game is over        break gameLoop    case let newSquare where newSquare > finalSquare:        // diceRoll will move us beyond the final square, so roll again        continue gameLoop    default:        // this is a valid move, so find out its effect        square += diceRoll        square += board[square]    }}print("Game over!")

 注意:如上如果使用break語句時沒有用gameLoop標籤,那麼break跳出來的不是while迴圈而是switch語句。

 

6.提前退出

guard 語句與if語句類似,都是根據一個運算式返回的布爾值來判斷是否執行。用gurad語句執行時guard後面代碼時必須要求guard語句的判斷條件為true。與if語句不一致的是,guard語句中else語句一直都會存在,當條件不滿足時,這個case語句就會執行。

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"])// Prints "Hello John!"// Prints "I hope the weather is nice near you."greet(person: ["name": "Jane", "location": "Cupertino"])// Prints "Hello Jane!"// Prints "I hope the weather is nice in Cupertino."

 如果guard語句中條件滿足,就會執行guard之外的代碼。任何在guard語句條件判斷中聲明的變數或者常量,在guard之外的代碼都可以使用。

如果條件不滿足,會執行code之外的代碼分支。在case分支中,你必須讓代碼結束執行。你可以用break,return,Continue、throw來實現。

 

7.檢查API的可行性

Swift的編譯是在檢查API的可行上進行的,確保你不用真的調用一個在實際執行任務中不能使用的API。

編譯器會用SDK有用的資訊檢查你的應用程式在你的代碼用到的所有API。當你使用一個停用API時,Swift會提示編譯時間錯誤資訊。

 

你可以在if或者guard語句中用availability條件,根據這些判斷你想在runtime用的API是否可有效,去有條件地執行代碼塊。當檢查API在代碼中是有效時,編譯器就用這些可行性的條件資訊。

if #available(iOS 10, macOS 10.12, *) {    // Use iOS 10 APIs on iOS, and use macOS 10.12 APIs on macOS} else {    // Fall back to earlier iOS and macOS APIs}

 

上面的可用性條件指定在iOS中,if語句的主體只在ios10中執行;在macOS,只有在macOS 10.12和之後。最後一個參數*是必需的,並指定在任何其他平台上,如果執行的是目標指定的最小部署目標。

 

在它的一般形式中,可用性條件包含一個平台名稱和版本的列表。您可以使用平台名稱(如iOS、macOS、watchOS和tvos)作為完整的列表,參見聲明屬性。除了指定主要版本號碼,如iOS 8或macOS 10.10,您還可以指定較小的版本號碼,如ios8.3和macOS 10.10.3。

if #available(platform name version, ..., *) {    statements to execute if the APIs are available} else {    fallback statements to execute if the APIs are unavailable}

 

Swift--控制流程

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.