Swift 제어 흐름(Control Flow)

이재원·2024년 6월 27일
0

Swift

목록 보기
5/13
post-custom-banner

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!

반복문을 돌면서 원하는 만큼 범위를 건너뛰고 출력하려고 한다면stride(from:to:by:) 함수를 사용하면 됩니다.

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:through:by:) 를 사용하면 됩니다.

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)
}

Repeat-While

Repeat-While은 다른 언어의 do-while과 동일하다고 생각하면 됩니다. repeat-while 역시 repeat 구문 내에 있는 코드들을 먼저 실행한 후 while 반복문을 돌기 때문입니다.

var num = 0;

repeat {
  num += 1;
  print("num: \(num)")
} while num < 10;

// 1 먼저 출력한 후 나머지 출력

위 코드의 경우 1을 먼저 출력한 후 나머지 값들은 조건에 맞춰 출력되는 것을 확인할 수 있습니다.

다음 예제를 보도록 하겠습니다.

var num = 0;

repeat {
  num += 1;
  print("num: \(num)")
} while num < 0;

// num: 1 출력

이번 예제에서는 while 조건에 상관없이 repeat 구문 내에서 1이 먼저 출력되는 것을 확인할 수 있습니다.

이처럼 스위프트에서 repeat-while은 다른 언어에서의 do-while과 유사하다는 것을 알 수 있습니다.

조건 구문(Conditional Statements)

Swift에서 조건문은 기본적으로 다른 언어들과 거의 유사합니다. 따라서 조금 다른 점들만 정리해 보겠습니다.

let weatherAdvice = if temperatureInCelsius <= 0 {
    "It's very cold. Consider wearing a scarf."
} else if temperatureInCelsius >= 30 {
    "It's really warm. Don't forget to wear sunscreen."
} else {
    "It's not that cold. Wear a T-shirt."
}

print(weatherAdvice)
// Prints "It's not that cold. Wear a T-shirt."

이 예제를 보면 if 조건문에서 참이 되면, 해당되는 값이 바로 상수에 할당됩니다.

if 구문에서 모두 동일한 타입의 값을 포함해야 합니다. Swift는 각 분기의 타입을 개별적으로 확인하기 때문에 둘 이상의 타입으로 사용될 수 있는 nil 과 같은 값은 Swift가 if 표현식의 타입을 자동으로 결정하는 것을 방지합니다. 대신에 타입을 명시적으로 지정해야 합니다.

let freezeWarning: String? = if temperatureInCelsius <= 0 {
    "It's below freezing. Watch for ice!"
} else {
    nil
}

위의 코드에서 if 표현식 중 하나의 분기는 문자열 값을 가지고 다른 분기는 nil 값을 가집니다. nil 값은 모든 옵셔널 타입의 값으로 사용될 수 있으므로 옵셔널 문자열이라고 명시적으로 작성되어야 합니다.

let freezeWarning = if temperatureInCelsius <= 0 {
    "It's below freezing. Watch for ice!"
} else {
    nil as String?
}

Switch

Swift에서 Switch는 break 없이 처음 일치하는 switch 케이스가 완료되자마자 switch 구문 전체가 끝납니다. C에서와는 달리 사용을 좀 더 쉽게 해주고 실수로 케이스가 하나 이상 실행되는 것을 피할 수 있습니다.

명시적 fallthrough (No Implicit Fallthrough)

각 케이스의 본문은 반드시 적어도 하나의 실행가능한 구문이 포함되어야 합니다.

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.

위 코드는 첫번째 케이스가 비어 있으므로 유효하지 않습니다. 또한 C언어에서와 다르게 a와 A가 일치하지 않습니다. 따라서 위 코드는 실행 가능한 구문이 없기 때문에 컴파일 때 에러가 발생합니다.

만약 두 문자가 모두 일치하는 단일 케이스를 만드려면 콤마로 합쳐주면 됩니다.

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)

케이스 안에 값은 간격을 포함하여 확인할 수 있습니다.

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."

위 예제에서 approximateCount 는 12와 100 사이에 있기 때문에 dozens of가 출력됩니다.

튜플(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"

위 예제에서 만약 somePoint가 (0, 0)이라면 4개 케이스에 모두 일치하는데, 이 경우에는 첫번째 일치하는 케이스가 항상 사용되고 나머지 케이스들은 모두 무시됩니다.

값 바인딩(Value Bindings)

switch 케이스는 일치하는 값 또는 값들을 임시적 상수 또는 변수로 이름을 가질 수 있으며 케이스 본문 안에서 사용할 수 있습니다. 값은 케이스 의 본문 내부에서 임시적 상수 또는 변수로 바인드 되기 때문에 이러한 동작을 값 바인딩이라고 합니다.

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"

위 예제는 첫번째 케이스에서 y는 0이고 x의 값은 임시적으로 상수 x에 할당한 것과 일치합니다. 따라서 위 예제에서는 y가 0인 첫번째 케이스가 anotherPoint에 할당된 값과 일치하므로 첫번째 케이스의 구문이 출력됩니다.

또한 위 예제에서는 default 케이스를 가지고 있지 않는데, 마지막 케이스 case let (x,y) 가 어떠한 값도 받을 수 있으므로 default 케이스가 필요하지 않습니다.

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"

위 예제처럼 where 절의 조건이 참인 경우에 해당 구문이 실행됩니다. 위 코드 역시 마지막 케이스가 모든 값을 받을 수 있으므로 default 케이스가 필요하지 않습니다.

출처
https://bbiguduk.gitbook.io/swift/language-guide-1/control-flow

profile
20학번 새내기^^(였음..)
post-custom-banner

0개의 댓글