Swift Doc 톺아보기 (4) - 제어흐름

요나·2023년 5월 9일
0

Swift Doc 톺아보기

목록 보기
4/4

이 글은 https://bbiguduk.gitbook.io/swift 에 나오는 스위프트 문법을 공부하면서 새롭게 알게 된 지식들을 정리한 포스팅입니다.


For-In 루프 (For-In Loops)

  • for-in 루프를 돌기 위해서는 해당 콜랙션은 시퀀스(Sequence) 프로토콜을 준수해야 한다.
  • 카운터 값을 사용하지 않을 때는 _로 대체할 수 있다.
let base = 3
let power = 10
var answer = 1

for _ in 1...power {
		answer *= base
}

print(answer) // 59049
  • stride(from:to:by:) : 반열림 범위 연산자(..<)와 같은 기능이되 간격을 설정할 수 있다.
    • stride(from:through:by:) : 닫힌 범위 연산자(...)와 같은 기능이되 간격을 설정할 수 있다.
let minuits = 60
let hours = 12
let hoursInterval = 3

for tick in stride(from: 0, to: minuits, by: 5) {
    print(tick) // 0 5 10 ... 45 50 55
}

for tick in stride(from: 0, through: hours, by: hoursInterval) {
    print(tick) // 3 6 9 12
}

Switch

  • switch 구문은 여러 패턴 중 첫번째로 일치하는 case에 해당하는 코드 블럭을 실행한다.
  • 암시적 Fallthrough 불가 (No Implicit Fallthrough)
    • C나 Obj-C와 다르게, Swift의 switchbreak 없이도 해당 case 끝나면 switch 빠져나간다.
    • 그렇기 때문에 각 case는 반드시 하나 이상의 실행가능한 구문이 포함되어야 한다.
    • 여러 값에 일치하는 단일 케이스를 만들 때는 ,로 구분하여 하나의 case로 결합한다.
let lowerCaseA: Character = "a"

switch lowerCaseA {
// case "a": // 에러
// case "A":
case "a", "A":
    print("This is letter A")
default:
    print("This is not A")
}
  • 간격 일치 (Interval Matching)
    • 범위 연산자로 해당 값에 대한 case를 확인할 수 있다.
let num: Int = 50
switch num {
case ..<50:
    print("less than 50")
case 50..<100:
    print("less than 100")
case 100...:
    print("more than 100")
default:
    print("??")
}
  • 튜플 (Tuples)
    • switchcase로 튜플을 사용할 수 있으며 각 요소는 값 또는 범위가 될 수 있다.
    • _로 어떤 값도 일치하는 와일드카드 패턴을 사용할 수 있다.
    • 아래 예제에서 (0, 0)은 모든 케이스에 해당되지만 첫번째 일치하는 case만 사용된다.
let somePoint: (Int, Int) = (1, 1)
switch somePoint {
case (0, 0):
    print("origin")
case (_, 0):
    print("x-axis")
case (0, _):
    print("y-axis")
case (-2...2, -2...2):
    print("inside of box")
default:
    print("outside of bax")
}
  • 값 바인딩 (Value Bindings)
    • case에 일치하는 값을 상수나 변수에 할당하여 구문 내에서 사용할 수 있다.
    • 아래 예제에서 마지막 case가 가능한 남아있는 모든 경우와 일치하기 때문에 default가 필요없다.
let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
    print("\(x) on the x-axis")
case (0, var y):
    print("\(y) on the y-axis")
case let (x, y):
    print("\(x) and \(y)")
}
  • Where
    • case의 추가 조건으로 where절을 사용할 수 있다.
    • 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) not on a line")
}
  • 혼합 케이스 (Compound Cases)
    • 각 패턴 사이에 ,를 구분자로 하여 여러 개의 패턴을 하나의 단일 케이스로 결합 가능하다.
    • 혼합 케이스는 값 바인딩을 포함할 수 있다.
      • 모든 패턴은 동일한 이름의 변수/상수로 묶여야 하며, 동일한 타입의 값을 할당받아야 한다.
      • 아래 예제처럼 한 case에서 튜플 내 서로 다른 값이 바인딩될 때, 다른 타입이면 에러 발생한다.
let stillAnotherPoint = (9, 0) // (Int, String) 등은 불가.
switch stillAnotherPoint {
case (let distance, 0), (0, let distance):
    print("On an axis, and \(distance) from origin")
default:
    print("Not on an axis")
}

제어 변경 구문 (Control Transfer Statements)

  • Break
    • switch 구문에서 의도적으로 case를 무시하기 위해서 break 구문을 사용한다.
      • 모든 케이스에 대하여 값을 처리할 수 없을 경우에 주로 사용한다.
  • Falltrough
    • switch 구문에서 해당 케이스 본문을 실행한 후 다음 케이스로 넘어갈 때 falltrough 사용한다.
    • fallthrough는 다음 케이스의 조건을 확인하지 않고 (default가 아니어도) 무조건 실행한다.
let number: Int = 5
var result: String = "This is a number of "
switch number {
case 2, 3, 5, 7, 11, 13, 17, 19:
    result += "prime number and "
    fallthrough
//case 6:
//    result += "??"
default:
    result += "integer"
}

print(result) // This is a number of prime number and integer
// 주석 지우면: This is a number of prime number and ??
  • 라벨이 있는 구문 (Labeled Statements)
    • 조건 구문(if, switch)이나 루프 구문(for, while)에 구문 라벨을 붙일 수 있다.
    • 조건 구문: break 사용 가능 / 루프 구문: break, continue 사용 가능
    • 아래 예제에서 break는 라벨을 써야되지만, continue는 필수는 아니다. (가독성 위해 권장)
gameLoop: while square != finalSquare {
    dice += 1
    if dice == 7 { dice = 1 }
    switch square + dice {
    case finalSquare:
        break gameLoop // 라벨을 쓰지 않으면 switch가 break 된다.
    case let newSquare where newSquare > finalSquare:
        continue gameLoop // 라벨을 쓰지 않아도 while이 continue되지만, 가독성 위해 쓴다.
    default:
        square += dice
        square += board[square]
        print(square)
    }
}

print("END!")

이른 종료 (Early Exit) → Guard

  • guard 구문은 항상 else 절을 가지며, else 절의 코드는 조건이 거짓일 경우에만 실행된다.
    • 이른 종료 로직을 짤 때 메인 코드를 else 블럭으로 래핑하지 않아도 되기에 if 보다 선호된다.
  • 무조건 return, break, continue, throw 등의 탈출로직이 수반되어야만 한다.
  • 일반적인 조건문을 쓸 수도 있지만, guard 구문은 주로 옵셔널 바인딩에 사용한다.
    • 옵셔널 바인딩한 상수/변수는 guard 스코프(중괄호) 바깥에서 사용가능하다.
    • 아래 예제처럼 옵셔널한 값(딕셔너리 서브 스크립트)을 체크하여 이른 종료할 때 사용한다.
func greet(person: [String: String]) {
//    guard person.count > 1 else {
//        print("You gave less information..")
//        return
//    }
    
    guard let name = person["name"] else {
        return
    }
    
    print("Hello \(name)!")

    
    guard let location = person["location"] else {
        print("You're Homeless.")
        return
    }
    
    print("You live in \(location).")
}

greet(person: ["name": "Yohan"])

연기된 동작 (Deffered Actions) → Defer

  • defer 블럭 안의 코드는 현재 스코프의 마지막 순서에 실행된다.
  • 함수의 이른 종료, for 루프의 break, 에러 throw 등도 포함된다.
  • defer 블럭이 여러 개일 경우는 역순으로 실행된다.
  • 런타임 에러가 발생하면 연기된 동작은 수행되지 않는다.
var score: Int = 3
if score < 100 {
    score += 100
    defer {
        score -= 100 // 4: -50
    }
    defer {
        score += 50 // 3: 50
    }
    defer {
        score *= 0 // 2: 0
    }
    print(score) // 1: 103
}
print(score)) // -50

사용 가능한 API 확인 (Checking API Availablity)

  • 사용하려는 API가 현재 런타임에서 사용할 수 있는지의 여부를 if/guard 구문으로 확인할 수 있다.
    • 가용성/비가용성 조건(availablilty condition) #available #unavailable을 사용한다.
    • 각 플랫폼 이름과 버전을 나열한 뒤, 최소 타겟 버전에서 실행하도록 지정하는 * 마지막에 입력.
@available(macOS 10.12, *)
struct ColorPreference {
    var bestColor = "blue"
}

func chooseBestColor() -> String {
    guard #available(macOS 10.12, *) else {
        return "gray"
    }
    let colors = ColorPreference()
    return colors.bestColor
}

print(chooseBestColor()) // blue
profile
var yona = IOSDeveloper(stage: 0)

0개의 댓글