Control Flow

iamgroot1231·2022년 6월 7일
0

Swift Language Guide

목록 보기
6/10
post-thumbnail

Swift Language Guide - Control Flow

  • Swift는 다양한 제어 흐름 명령문을 제공합니다. 여기에는 작업을 여러 번 수행하는 while 루프가 포함됩니다.
  • 특정 조건에 따라 코드의 다른 분기를 실행하기 위한 if, guard 및 switch 문이 있습니다.
  • break 및 continue와 같은 명령문은 실행 흐름을 코드의 다른 지점으로 전송합니다.
  • Swift는 배열, Dictionary, 범위, 문자열 및 기타 시퀀스를 쉽게 반복할 수 있는 for-in 루프를 제공합니다.

    Swift의 switch 문은 많은 C 유사 언어의 해당 문보다 훨씬 더 강력합니다. case 간격 일치, 튜플 및 특정 유형으로의 캐스트를 포함하여 다양한 패턴과 일치할 수 있습니다. switch case에서 일치하는 값은 case 본문 내에서 사용하기 위해 임시 상수 또는 변수에 바인딩될 수 있으며 복잡한 일치 조건은 각 case에 대한 where 절로 표현될 수 있습니다.


📌 For-In Loops

  • 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!
  • Dictionary를 반복하여 키-값 쌍에 액세스할 수도 있습니다.
  • Dictionary의 각 항목은 Dictionary이 반복될 때 (키, 값) 튜플로 반환되며 for-in 루프의 본문 내에서 사용하기 위해 명시적으로 명명된 상수로 (키, 값) 튜플의 멤버를 분해할 수 있습니다.
  • 아래 코드 예제에서 Dictionary의 키는 animalName이라는 상수로 분해되고 Dictionary의 값은 legCount라는 상수로 분해됩니다.
    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
  • 숫자 범위와 함께 for-in 루프를 사용할 수도 있습니다. 이 예에서는 5의 배수를 인쇄합니다.
    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
  • 시퀀스의 각 값이 필요하지 않은 경우 변수 이름 대신 밑줄을 사용하여 값을 무시할 수 있습니다.
    let base = 3
    let power = 10
    var answer = 1
    for _ in 1...power {
        answer *= base
    }
    print("\(base) to the power of \(power) is \(answer)")
    // Prints "3 to the power of 10 is 59049"
  • 어떤 상황에서는 두 끝점을 모두 포함하는 닫힌 범위를 사용하고 싶지 않을 수 있습니다.
  • 예를들어 시계를 표현하고 싶을때, 0분부터 시작하여 60개의 눈금을 그리고 싶습니다.
  • `하한은 포함하지만 상한은 포함하지 않으려면 반개방 범위 연산자(..<)를 사용합니다.
    let minutes = 60
    for tickMark in 0..<minutes {
        // render the tick mark each minute (60 times)
    }
  • 일부 사용자는 UI에서 더 적은 눈금 표시를 원할 수 있습니다. 그들은 대신 5분마다 한 표씩을 선호할 수 있습니다. stride(from:to:by:) 함수를 사용하여 원하지 않는 표시를 건너뜁니다.
    ```swift    
    let minuteInterval = 5
    for 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(부터):to(전 까지):by(단위로):)

  • stride(from:through:by:) 를 사용하여 닫힌 범위를 사용할 수도 있습니다.
    ```swift    
    let hours = 12
    let hourInterval = 3
    for tickMark in stride(from: 3, through: hours, by: hourInterval) {
        // render the tick mark every 3 hours (3, 6, 9, 12)
    }
    ```

    stride(from(부터):through(까지):by(단위로):)


📌 While Loops

  • while 루프는 조건이 거짓이 될 때까지 일련의 명령문을 수행합니다.
  • 이러한 종류의 루프는 첫 번째 반복이 시작되기 전에 반복 횟수를 알 수 없을 때 가장 잘 사용됩니다.
  • Swift는 두 가지 종류의 while 루프를 제공합니다.

📍 While

  • while 루프는 조건이 참이면 조건이 거짓이 될 때까지 일련의 명령문이 반복합니다.

  • 다음은 while 루프의 일반적인 형식입니다.

        while condition {
            statements
        }
  • 아래의 예는 뱀과 사다리의 간단한 게임을 보여줍니다.

    • 게임의 규칙
      - 보드에는 25개의 사각형이 있으며 목표는 사각형 25 이상에 착지하는 것입니다.
      - 플레이어의 시작 사각형은 보드의 왼쪽 하단 모서리에서 약간 떨어진 "0제곱"입니다.
      - 각 턴에 6면체 주사위를 굴리고 위의 점선 화살표로 표시된 수평 경로를 따라 해당 칸만큼 이동합니다.
      - 당신의 차례가 사다리의 맨 아래에서 끝나면, 당신은 그 사다리를 올라갑니다.
      - 당신의 턴이 뱀의 머리에서 끝나면 당신은 그 뱀의 아래로 이동합니다.
      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 {
        // roll the dice
        diceRoll += 1
        if diceRoll == 7 { diceRoll = 1 }
        // move by the rolled amount
        square += diceRoll
        if square < board.count {
            // if we're still on the board, move up or down for a snake or a ladder
            square += board[square]
        }
    }
    print("Game over!")
    
  • while 루프가 시작될 때 게임의 길이가 명확하지 않기 때문에 이 경우에 while 루프가 적절합니다. 대신 특정 조건이 충족될 때까지 루프가 실행됩니다.

📍 Repeat-While

  • while 루프의 다른 변형인 repeat-while 루프는 루프의 조건을 고려하기 전에 루프 블록을 먼저 한 번 수행합니다.
  • 그런 다음 조건이 거짓일 때까지 루프를 continue 반복합니다.
    repeat {
        statements
    } while condition
  • 뱀과 사다리 게임 repeat while 구현
    repeat {
        // move up or down for a snake or ladder
        square += board[square]
        // roll the dice
        diceRoll += 1
        if diceRoll == 7 { diceRoll = 1 }
        // move by the rolled amount
        square += diceRoll
    } while square < finalSquare
    print("Game over!")
  • 루프의 조건(square < finalSquare)은 이전과 동일하지만, 이번에는 루프를 통한 첫 번째 실행이 끝날 때까지 평가되지 않습니다.

📌 Conditional Statements

  • 특정 조건에 따라 다른 코드 조각을 실행하는 것이 종종 유용합니다.
  • 이렇게 하려면 코드의 일부를 조건부로 만듭니다.
  • Swift는 코드에 조건 분기를 추가하는 두 가지 방법인 if 문과 switch 문을 제공합니다.
  • 일반적으로 if 문을 사용하여 몇 가지 가능한 결과만 있는 간단한 조건을 평가합니다.
  • switch 문은 가능한 순열이 여러 개인 더 복잡한 조건에 더 적합하며 패턴 일치가 실행할 적절한 코드 분기를 선택하는 데 도움이 될 수 있는 상황에서 유용합니다.

📍 If

  • 가장 간단한 형태의 if 문에는 단일 if 조건이 있습니다. 해당 조건이 참인 경우에만 일련의 명령문을 실행합니다.
    var temperatureInFahrenheit = 30
    if temperatureInFahrenheit <= 32 {
        print("It's very cold. Consider wearing a scarf.")
    }
    // Prints "It's very cold. Consider wearing a scarf."
  • if 문은 if 조건이 false인 상황에 대해 else 절로 알려진대체 명령문을 제공할 수 있습니다. 이러한 명령문은 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.")
    }
    // Prints "It's not that cold. Wear a t-shirt."
  • 여러 if 문을 함께 연결하여 추가 절을 고려할 수 있습니다.
    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.")
    }
    // Prints "It's really warm. Don't forget to wear sunscreen."
  • 마지막 else 절은 선택 사항이며 조건 집합을 완료할 필요가 없는 경우 제외할 수 있습니다.
    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 문은 값을 고려하고 여러 가능한 일치 패턴과 비교합니다. 그런 다음 성공적으로 일치하는 첫 번째 패턴을 기반으로 적절한 코드 블록을 실행합니다.
  • 가장 간단한 형태의 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
    }
  • 모든 switch 문은 철저해야 합니다. 즉, 고려 중인 유형의 모든 가능한 값은 switch case 중 하나와 일치해야 합니다.
  • 가능한 모든 값에 대해 case를 제공하는 것이 적절하지 않은 경우 명시적으로 처리되지 않은 값을 포함하도록 Default case를 정의할 수 있습니다. 이 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"

📍 No Implicit Fallthrough

  • C 및 Objective-C의 switch 문과 달리 Swift의 switch 문은 기본적으로 각 사례의 맨 아래를 통과하여 다음 사례로 넘어가지 않습니다.
  • switch 문은 명시적인 break 문을 요구하지 않고 첫 번째로 일치하는 case가 발견되는 즉시 실행을 완료합니다.
  • 이것은 switch 문을 C의 것보다 더 안전하고 사용하기 쉽게 만들고 실수로 둘 이상의 switch case를 실행하는 것을 방지합니다.

    Swift에서는 break가 필요하지 않지만 break 문을 사용하여 특정 case를 일치 및 무시하거나 해당 case가 실행을 완료하기 전에 일치된 case에서 벗어날 수 있습니다.

  • 각 case의 본문에는 실행 가능한 명령문이 하나 이상 포함되어야 합니다.
    let anotherCharacter: Character = "a"
    switch anotherCharacter {
    case "a": // Invalid, the case has an empty body
    case "A":
        print("The letter A")
    default:
        print("Not the letter A")
    }
    // This will report a compile-time error.
  • "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"

📍 Interval Matching

  • switch case의 값은 간격에 포함되었는지 확인할 수 있습니다. 이 예에서는 숫자 간격을 사용하여 모든 크기의 숫자에 대해 자연어 개수를 제공합니다.
    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).")
    // Prints "There are dozens of moons orbiting Saturn."

📍 Tuples

  • 튜플을 사용하여 동일한 switch 문에서 여러 값을 테스트할 수 있습니다.
  • 튜플의 각 요소는 다른 값 또는 값 간격에 대해 테스트할 수 있습니다. 또는 와일드카드 패턴이라고도 하는 밑줄 문자(_)를 사용하여 가능한 값과 일치시킵니다.
  • 아래 예제는 (Int, Int) 유형의 단순 튜플로 표현되는 (x, y) 점을 가져와서 예제를 따르는 그래프에서 범주화합니다.
    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")
    }
    // Prints "(1, 1) is inside the box"
  • 위의 switch 문은 점이 원점(0, 0)에 있는지, 빨간색 x축에 있는지, 녹색 y축에 있는지, 원점을 중심으로 하는 파란색 4x4 상자 내부 또는 상자 외부에 있는지 결정합니다.
  • 다중 일치가 가능한 경우 일치하는 가장 첫 번째 case의 명령문이 사용됩니다.

📍 Value Bindings

  • switch case는 case 본문에 사용하기 위해 임시 상수 또는 변수와 일치하는 값 또는 값의 이름을 지정할 수 있습니다.
  • 값이 case 본문 내의 임시 상수 또는 변수에 바인딩되기 때문에 이 동작을 값 바인딩이라고 합니다.
  • 아래 예제는 (Int, Int) 유형의 튜플로 표현되는 (x, y) 점을 가져와 다음 그래프에 분류합니다.
    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"
  • 세 개의 switch case는 자리 표시자 상수 x 및 y를 선언하며, 이 상수는 anotherPoint에서 하나 또는 둘 모두의 튜플 값을 일시적으로 사용합니다.
  • 임시 상수가 선언된 후에는 case의 코드 블록 내에서 사용할 수 있습니다. 여기에서 포인트의 분류를 인쇄하는 데 사용됩니다.
  • 이 switch 문에는 기본 case가 없습니다. 마지막 경우인 case let (x, y)는 모든 값과 일치할 수 있는 두 개의 자리 표시자 상수의 튜플을 선언합니다.
  • anotherPoint는 항상 두 값의 튜플이기 때문에 이 경우는 가능한 모든 나머지 값과 일치하며 기본 경우는 필요하지 않습니다.

📍 Where

  • switch case는 where 절을 사용하여 추가 조건을 확인할 수 있습니다.
  • 아래 예는 다음 그래프에서 (x, y) 점을 분류합니다.
    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"

📍 Compound Cases

  • 동일한 본문을 공유하는 여러 switch 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) isn't a vowel or a consonant")
    }
    // Prints "e is a vowel"
  • 복합 사례에는 값 바인딩도 포함될 수 있습니다.
  • 복합 사례의 모든 패턴은 동일한 값 바인딩 집합을 포함해야 하며 각 바인딩은 복합 사례의 모든 패턴에서 동일한 유형의 값을 가져와야 합니다.
  • 아래의 예는 복합 case가 일치하는 부분에 관계없이 본문의 코드가 항상 바인딩 값에 액세스할 수 있고 값이 항상 동일한 유형을 갖도록 합니다.
    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")
    }
    // Prints "On an axis, 9 from the origin"

📌 Control Transfer Statements

  • 제어 전송 문은 코드의 한 부분에서 다른 부분으로 제어를 전송하여 코드가 실행되는 순서를 변경합니다. Swift에는 5개의 제어 전송 명령문이 있습니다.
    • continue
    • break
    • fallthrough
    • return
    • throw

📍 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
        }
        puzzleOutput.append(character)
    }
    print(puzzleOutput)
    // Prints "grtmndsthnklk"

📍 Break

  • break 문은 전체 제어 흐름 문의 실행을 즉시 종료합니다.
  • break 문은 switch 또는 루프 문의 실행을 루프의 종료보다 일찍 종료하려는 경우 switch 또는 루프 문 내에서 사용할 수 있습니다.

📌 Break in a Loop Statement

  • 루프 문 내에서 사용되는 경우 break는 루프 실행을 즉시 종료하고 루프의 닫는 중괄호(}) 뒤의 코드로 제어를 전달합니다.
  • 루프의 현재 반복에서 더 이상 코드가 실행되지 않고 루프의 더 이상 반복이 시작되지 않습니다.

📌 Break in a Switch Statement

  • switch 문 내에서 break를 사용하면 switch 문이 즉시 실행을 종료하고 switch 문의 닫는 중괄호(}) 뒤의 코드로 제어를 넘깁니다.
  • 이 동작은 switch 문에서 하나 이상의 case를 일치시키고 무시하는 데 사용할 수 있습니다.
  • 무시하려는 case의 전체 본문으로 break 문을 작성하여 이를 수행합니다.

    주석만 포함된 switch case는 컴파일 타임 오류로 보고됩니다. 주석은 코드가 아니며 switch case를 무시하지 않습니다. switch case를 무시하려면 항상 break 문을 사용하십시오.

    let numberSymbol: Character = "三"  // Chinese symbol for the number 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 couldn't be found for \(numberSymbol).")
    }
    // Prints "The integer value of 三 is 3."

📍 Fallthrough

  • Swift에서 switch 문은 각 case의 맨 아래에서 다음 case로 넘어가지 않습니다. 즉, 첫 번째 일치하는 경우가 완료되는 즉시 전체 switch 문 실행이 완료됩니다.
  • fallthrough 동작이 필요한 경우 fallthrough 키워드를 사용하여 사례별로 이 동작을 선택할 수 있습니다.
    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)
    // Prints "The number 5 is a prime number, and also an integer."
  • fallthrough 키워드를 사용하여 기본 case의 명령이 실행 됩니다. 기본 case는 설명 끝에 몇 가지 추가 텍스트를 추가하고 switch 문이 완료됩니다.

📍 Labeled Statements

  • Swift에서 다른 루프 및 조건문 내부에 루프 및 조건문을 중첩하여 복잡한 제어 흐름 구조를 생성할 수 있습니다.

  • 그러나 루프와 조건문은 모두 break 문을 사용하여 실행을 조기에 종료할 수 있습니다.

  • 따라서 break 문이 종료되기를 원하는 루프 또는 조건문을 명시하는 것이 때때로 유용합니다.

  • 여러개의 루프 문을 사용하면 break 또는 continue 문과 함께 레이블 문을 사용하여 레이블이 지정된 문의 실행을 종료하거나 continue할 수 있습니다.

  • 레이블이 지정된 명령문은 명령문의 소개 키워드와 같은 줄에 레이블을 배치하고 콜론이 뒤에 오는 것으로 표시됩니다.

    label name: while condition {
        statements
    }
  • 다음 예제에서는 이 장의 앞부분에서 본 Snakes and Ladders 게임의 개조된 버전에 대해 레이블이 지정된 while 루프와 함께 break 및 continue 문을 사용합니다. 이번에는 게임에 추가 규칙이 있습니다.

    • 이기려면 정확히 25번 칸에 착지해야 합니다.
  • 이 게임 버전은 게임 로직을 구현하기 위해 while 루프와 switch 문을 사용합니다. while 루프에는 뱀과 사다리 게임의 기본 게임 루프임을 나타내는 gameLoop라는 명령문 레이블이 있습니다.

    ```swift
    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
    
    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 레이블을 사용하지 않은 경우 while 문이 아니라 switch 문에서 중단됩니다. gameLoop 레이블을 사용하면 어떤 제어 문을 종료해야 하는지 명확히 알 수 있습니다.
    루프의 다음 반복으로 점프하기 위해 continue gameLoop를 호출할 때 gameLoop 레이블을 사용할 필요는 없습니다.
    게임에는 루프가 하나만 있으므로 continue 문이 어떤 루프에 영향을 미칠지 모호하지 않습니다.
    그러나 continue 문과 함께 gameLoop 레이블을 사용하는 것은 아무런 문제가 없습니다. 그렇게 하는 것은 break 문과 함께 레이블을 사용하는 것과 일치하며 게임의 논리를 읽고 이해하기 쉽게 만드는 데 도움이 됩니다.


📌 Early Exit(guard)

  • if 문과 같은 guard 문은 표현식의 부울 값에 따라 문을 실행합니다.

  • guard 문을 사용하여 guard 문 뒤의 코드가 실행되려면 조건이 참이어야 합니다.

  • if 문과 달리 보호 문에는 항상 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"])
    // 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 문이 표시되는 나머지 코드 블록에 사용할 수 있습니다.

  • 해당 조건이 충족되지 않으면 else 분기 내의 코드가 실행됩니다. 해당 분기는 보호 문이 나타나는 코드 블록을 종료하기 위해 제어를 전송해야 합니다.

  • return, break, continue, throw와 같은 제어 전달 문으로 이 작업을 수행할 수도 있고, fatalError(_:file:line:)와 같이 반환하지 않는 함수나 메서드를 호출할 수도 있습니다.

  • 요구 사항에 대해 guard 문을 사용하면 if 문으로 동일한 검사를 수행하는 것과 비교하여 코드의 가독성이 향상됩니다.

  • 이를 통해 일반적으로 실행되는 코드를 else 블록으로 래핑하지 않고 작성할 수 있으며 위반된 요구 사항을 처리하는 코드를 요구 사항 옆에 유지할 수 있습니다.


📌 Checking API Availability

  • Swift에는 API 가용성 확인을 위한 지원 기능이 내장되어 있어 주어진 배포 대상에서 사용할 수 없는 API를 실수로 사용하지 않도록 합니다.
  • 컴파일러는 SDK의 가용성 정보를 사용하여 코드에 사용된 모든 API가 프로젝트에서 지정한 배포 대상에서 사용 가능한지 확인합니다.
  • Swift는 사용할 수 없는 API를 사용하려고 하면 컴파일 시간에 오류를 보고합니다.
  • 사용하려는 API가 런타임에 사용 가능한지 여부에 따라 if 또는 보호 문에서 가용성 조건을 사용하여 코드 블록을 조건부로 실행합니다.
  • 컴파일러는 해당 코드 블록의 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 문의 본문이 iOS 10 이상에서만 실행되도록 지정합니다. macOS에서는 macOS 10.12 이상에서만 가능합니다.
  • 마지막 인수인 *는 필수이며 다른 플랫폼에서 if의 본문이 대상에서 지정한 최소 배포 대상에서 실행되도록 지정합니다.
  • 일반적인 형식에서 가용성 조건은 플랫폼 이름 및 버전 목록을 사용합니다. iOS, macOS, watchOS 및 tvOS와 같은 플랫폼 이름을 사용합니다. 전체 목록은 선언 속성을 참조하세요.
  • iOS 8 또는 macOS 10.10과 같은 주 버전 번호를 지정하는 것 외에도 iOS 11.2.6 및 macOS 10.13.3과 같은 부 버전 번호를 지정할 수 있습니다.
    if #available(platform name version, ..., *) {
        statements to execute if the APIs are available
    } else {
        fallback statements to execute if the APIs are unavailable
    }
profile
행복을 주는 iOS 개발자입니다.

0개의 댓글