brunch

You can make anything
by writing

C.S.Lewis

by MJ Apr 02. 2017

3. Swift의 제어문

Swift 3.x Programming

제어문은 프로그램의 실행흐름을 제어하기 위한 구문을 말한다. Swift언어에서는 프로그램의 조건분기 밒 반복을 위한 제어문등이 준비되어 있다.


1. 프로그램의 실헹흐름 제어하기

프로그램은 일반적으로 위에서 아래로 순서대로 실행되지만, 실제 개발에서는 조건에 따라 분기를 만들거나, 반복을 실시해야 하는 경우가 필요하다. 또한, 실행중인 프로세스를 중단하고 제어를 다른 곳으로 이동시키는 경우도 있다.

이런 프로그램의 실행 흐름을 제어하는 것이 제어문이다. Swift 언어의 제어문은 알맞고 다양한 용도에 적합한 것들이 준비되어 있다.

분기하는 제어문은 if문, guard문, switch문이 있고, 구문을 반복 제어하는 구문은 for문, while문이 있다. 또한 프로그램 제어를 이동시켜주는 failthrough문, break문, continue문이 있다.


2. 조건분기문

조건분기문은 식의 값에 따라 실행하는 문장을 전환하는 의미가 있다. Swift언어의 조건분기문은 if문 및 switch문이 있다.


if문

if문은 조건식의 성패에 따라 실행문을 전환하기 위한 제어문이다. if문은 아래와 같은 조건식과 연속으로 { }으로 둘러싸인 실행문으로 구성되어 있다. if문의 조건식이 true를 돌려주어야만 { }내 실행문을 실행하고 조건값이 false이면 { }내 실행문을 건너뛴다.


if 조건식 {

    조건식이 true일 경우에만 실행되는 문장

}


아래 예는 Int형 couponlimits값이 3이하면 메시지를 출력하고 3보다 크면 출력하지 않는 조건문을 만들어보았다.


let couponLimits = 2

if couponLimits <= 3 {

    print("쿠폰이 3일이내 만료됩니다")

}


if문에서는 조건식은 Bool형 값을 리턴해준다. 이때 리턴하는 식에는 비교연산자등의 결과가 있다.


let a = 3

if a > 0 {

    print("a는 0보다 크다")

}


주의해야 할 점은 결과값이 Bool형 이외에는 다른 자료형은 인정되지 않는다. 즉, Swift 언어의 if문은 Bool형 값이 조건이 성립여부에 명시해야 한다. 물론 다른언어로 개발해보신 분들 중 이 언어 사양이 범거롭다고 느낄 수 있지만 참거짓값에 대한 예상하지 못한 오류를 예방하기 위해 명확한 조건이 중요하다는 것이다.

만약 조건의 불성립이 되는 경우에 실행되는 문장을 추가하려면 else절을 추가한다.


if 조건식 {

    조건식이 true인 경우 실행되는 문장

} else {

    조건식이 false인 경우 실행되는 문장

}


이를 실제 적용해보면 다음과 같다.


let couponLimits = 5

if couponLimits <= 3 {

    print("쿠폰이 3일이내 만료됩니다")

} else {

    print("아직 쿠폰을 사용할 수 있습니다")

}


또한 else절에 다른 if문을 추가해서 확장할 수있다. 이렇게 하면 여러가지 조건식에 의한 조건분기를 실현할 수 있다.


if문 조건식1 {

    조건식1이 true일 경우에 실행되는 문장

} else if 조건식2 {

    조건식1이 false이고 조건식2가 true일 경우 실행되는 문장

} else {

    조건식1, 조건식2가 false일 경우 실행되는 문장

}


이를 실제 코드로 적용해보면 다음과 같다.


let couponLimits = 1

if couponLimits < 0 {

    print("쿠폰이 만료되었습니다")

} else if couponLimits <=3 {

    print("쿠폰이 3일이내 만료됩니다")

} else {

    print("아직 쿠폰을 사용할 수 있습니다")

}

//결과: 쿠폰이 3일이내 만료됩니다.


couponLimits값은 0이상 3이하이이기 때문에 "쿠폰이 3일이내 만료됩니다"라는 메시지가 출력된다.

if-let문은 값의 유무를 통한 선택적 바인딩 조건분기문으로 Optional<Wrapped>형의 값유무에 따라 분기하고 값이 존재하는 경우에는 값을 꺼내서 사용도 가능하다. 값이 있으면 { }내의 실행문을 처리하고 nil인 경우 { }내의 실행문을 건너 뛴다. 만약 nil인 경우에도 실행하는 문장을 추가하려면 else절을 추가한다.


if let 상수명 = Optional<Wrapped>형 값 {

    값이 존재하는 경우 실행되는 문장

} else {

    값이 존재하지 않는 경우 실행되는 문장

}


예로 Int?형 상수 a에 값이 존재하면 Int형 정수 b에 값이 대입하여 실행문을 실행하는 구조를 보여준다.


let a = Optional(1)

if let b = a {

    print("값: \(b)")

} else {

    print("값 없음")

}

//결과: 값: 1


if-let문은 여러개의 Optional<Wrapped>형값을 동시에 꺼낼 수 있는데, 모든 우측에 값이 있는 경우에만 if문이 실행된다.

아래 예제는 두개의 String?형 a, b가 있고 이에 대한 값을 이용하는 방법을 보여준다.


let a = Optional("A")

let b = Optional("B")

if let x = a, let y = b {

    print("값: \(x), \(y)")

} else {

    print("값은 Int형 \(Int)")

}

//결과: 값: A, B


그외 if-let문에 선언된 상수는 { }내에서만 사용이 가능하다.

if-case문은 조건성립이 패턴매치에 의한 분기를 통해 처리할 경우 이용한다.


if case 패턴 = 제어문 {

    제어문패턴과 일치하는 경우 실행되는 문장

}


예로 Int형 값이 1이상 9이하면 처리되는 조건분기는 1 ... 9패턴을 사용하는 것을 살펴보자.


let a = 3

if case 1 ... 9 = a {

    print(1이상 10이하의 값")

}


guard문은 조건이 불성립될 때 빠르게 빠져나가게 하고 싶은 분기문에 사용한다. guard문은 if문과 같은 조건식 평가결과가 Bool형값에 따라 처리를 하는데 if문과는 다르게 후속처리를 하는데 있어서 true일 경우 조건을 지정한다.


guard문

guard문은 guard 키워드 조건식, else 키워드 그리고 { }으로 둘러싸인 문장으로 구성된다. guard문은 조건식이 false를 리턴하는 경우에만 { }내 문장을 실행하고 조건이 true를 리턴하는 경우, { }내 문장실행을 건너뛴다.


guard 조건식 else {

    조건식이 false인 경우 실행되는 문장

    guard 문장이 작성되는 범위 외부로 넘김

}


Int 형 a는 0미만으로 되어 있기 때문에 guard문 조건식이 성립되지 않고 else절 내 문장이 실행된다.


func examFunc() {

    let a = -1

    guard a >= 0 else {

         print("0미만입니다")

    }

    return 

}


guard문의 else절에서는 guard문이 포함된 범위에서 벗어나지 않는다. 범위에서 벗어는 것은 컴파일러에 의해 체크되기 때문에 guard문의 else절 이후 guard절 조건식이 반드시 성립되는 것을 컴파일시 보장한다. 아래 예는 Int형 a가 0보다 크면 print1(_:)함수에서 벗어나기 위한 guard문을 사용해보자.


func prinf1(_a: Int) {

    guard a > 0 else {

        return

    }

    print(a)

}


else절에서 guard문을 포함한 범위에서 벗어난다는 것은 print1(_:)함수에서 벗어난다는 것을 의미한다. 만약, guard문을 포함한 범위에서 벗어나지 못하는 경우 컴파일 오류가 발생한다.

또한, guard문에서도  guard-let문이나 guard-case문이 있다. guard-let문은 선언된 변수난 상수는 guard문에 포함된 범위라면 guard-let문 외부에서도 사용 가능하다는 것이다. 즉 앞에서 설명한 if-let문으로 선언된 변수나 상수는 { }내 문장에서만 사용가능했지만 guard-let문으로 선언된 변수나 상수는 guard문 이후에서도 사용 가능하다는 것이다. 이는 guard문 조건식이 충족하지 못하는 경우에는 범위를 벗어나기 때문에 guard문 이후에 변수나 상수가 보장되어 있기 때문이다.


func examFunc() {

    let a: Any = 1   

    guard let i = a as? Int else {

        print("a는 Int형 아님")

        return

    }

    print("값: Int형\(i)")

}

examFunc() //결과: 값: Int형1


지금까지 정리한 두가지 분기문의 차이를 감안하면 guard문은 빠르게 조건을 벗어나기 위한 제어문이라고 볼 수 있다. 좀더 두 가지의 차이점을 이해하기 위해 2개의 Int?형 인수에 모두 값을 가지고 있으면 그 합을 리턴하면 하나가 값이 없으면 nil을 리턴하는 동시에 값을 가지고 있지 않은 인수를 출력하는 프로그램을 만들어보자.                       


func add(_ a: Int?, _ b: Int?) -> Int? {

    let x: Int

    if let aa = a {

        x = aa

    } else {

        print("첫번째 인수에 값 없음")

        return nil

    }

    let y: Int

    if let bb = b {

        y = bb

    } else {

        print("두번째 인수에 값 없음")

        return nil

    }

    return x + y

}

add(Optional(3), Optional(5)) //8


guard문으로 구현하게 되면 guard-let문으로 선언된 상수는 { }외부에서 사용할 수 있어 따로 Int형을 선언을 외부에 할 필요가 없다.



func add(_ a: Int?, _ b: Int?) -> Int? {

    guard let aa = a else {

        print("첫번째 인수에 값없음")

        return nil

    }

    guard let bb = a else {

        print("두번째 인수에 값없음")

        return nil

    }

    return a + b

}

add(Optional(3), Optional(2)) //5


이렇게 조건에 따라 바로 나가게 하는 guard문을 사용하면 간단하게 해결된다. 또한 guard문에 나가는 처리를 하지 않으면 컴파일 오류가 발생하기 때문에 단순 실수를 미리 예방할수 있다.


switch문

switch문은 패턴을 이용하여 제어식값에 따라 실행문을 전환 제어문이다. 형식은 아래와 같으며, 각 패턴은 case키워드로 정의하고 어떤 패턴이 일치하지 않으면 실행문은 default키워드에 기본 케이스로 정의한다.


switch 제어식 {

    case 패턴1: 

        제어식패턴1에 매치했을 경우 실행되는 문장

    case 패턴2:

        제어식패턴2에 매치했을 경우 실행되는 문장

    default:

        어떤 패턴도 일치하지않는 경우 실행되는 문장

}


switch문에서 제어식이 패턴과 일치하는지를 위에서 아래로 순서대로 평가해서 실행한다. switch문에서 한번 매치되어 실행문을 실행하면 매칭을 종료하고 이후 패턴은 생략한다. 이 말은 중복된 패턴을 넣어도 중복된 패턴중 앞부분의 패턴이외에는 사용되지 않는다.


let a = 3 

switch a {

case Int.min ..< 0:

    print("a는 음수")

case 0 ..< Int.max:

    print("a는 양수")

default:

    print("0")

}


Swift언어의 switch문은 컴파일러에 의해 케이스를 어느정도 완성하지 않으면 컴파일오류가 발생한다. switch문에 여러가지 경우를 넣어 하나의 케이스가 매치시켜야 한다.

.apple, .banana, .grape 3가지 케이스를 가진 FruitEnum형의 값을 리턴해주는 제어문을 만들어보자.


enum fruitEnum {

    case apple

    case banana

    case grape

}

let a = fruitEnum.banana

switch a {

case .apple: 

    print("사과")

case .banana:

    print("바나나")

case .grape: 

    print("포도")

}


만약,  fruitEnum의 3가지 값을 switch문에서 사용할 떄 .grape를 빼놓고 선언하면 컴파일 오류가 발생한다. 즉, switch문의 완전성을 만족시키기 위해 제어식형이 취할 수 있는 모든 값을 케이스에 작성해야 한다. 즉 Bool형을 사용한다면 케이스에 true 및 false를 모두 만들어야 한다.

앞에서 이야기한 것처럼 기본 케이스와 다른 모든 경우가 일치하는 경우, 대응하기 위한 default키워드를 정의한다. 기본 케이스가 일치하지 않으면 완전성을 보증하기 위한 역할이다.


enum fruitEnum {

    case apple 

    case banana

    case lemon

}

let lemon = fruitEnum.lemon

switch lemon {

case .apple:

    print("사과")

case .banana:

    print("바나나")

default: 

    print("기본") // lemon 케이스가 없기 때문에 default로 처리된다


하지만 기본 케이스를 처리하는 것을 최소화하고, 개별 케이스를 열거하는 것이 바람직하다. switch문이 기본 케이스를 가지고 있는 경우 열거형에 새로운 케이스가 추가되어도 자동으로 기본 케이스에 매치되기 때문이다. 이런 경우는 완전성이 유지된 상태이기 때문에 컴파일 오류가 발생하지 않는다. 따라서 새롭게 추가된 것이 있는 경우, 프로그램내에서 기본 케이스로 처리되어 의도하지 않는 실행이 될 수 있다. 이런 경우를 대비하여 모든 경우의 케이스를 선언해주는 것이 좋다.

where키워드를 사용하면 케이스에 맞는 조건이 추가할 수 있다.


switch 제어식 {

    case 패턴 where 조건식: 

        제어식 패턴과 일치하거나, 조건식을 만족하는 경우 실행되는 문장

    default:

        제어식중 패턴에 일치하는 경우가 없는 경우 실행되는 문장

}


다음 예는 상수 a 값을 가지고 있기 때문에 case .exam (let aa)부분은 일치하지만 where aa>9라는 조건을 충족하지 않는다. 따라서 case .exam (let aa) where aa>9전체를 매치하지 않고 기본케이스로 처리된다.


let a: Int? = 1

switch a {

case .exam(let aa) where aa> 9:

    print("9보다 큰값 \(aa)이 있다")

default:

    print("값이 존재하지 않거나 9이하이다")

}



3. 반복문

반복문은 조건에 따라 문장 실행을 반복하는 것이며 Swift 언어의 반복문은 크게 for문과 while문이 있다.


for문

for문은 값의 연속을 표현하는 Sequence프로토콜을 지키는 형 요소에 접근하기 위한 제어문이다. Sequence프로토콜을 지키는 대표적인 형으로 Array<Element>형이나 Dictionary<Key, Value>형등의 컬렉션을 나타내는 형이 있다. 이 항목에서는 모든 요소에 순차적으로 접근하는 for-in문과 패턴이 일치하는 요소만 사용하려는 for-case문에 대해서 알아보자.

for-in문은 Sequence프로토콜을 지키는 형 요소는 for-in문을 사용하여 열거할 수 있다. for-in문 형은 다음과 같은 형태로 작성하며 for-in문은 각 요소를 순차적으로 실행문에 전달하면서 그 요소를 몇번 반복처리한다. for-in문에서 열거된 요소명은 자유롭게 결정할 수 있고그 이름에 상수가 정의된다.


for 요소 in 연속되는 값 {

    요소마다 반복되는 문장

}


Array<Element>형 요소를 for-in문에서 열거하는 경우 요소형태는 element형이다.


let arr = [1, 2, 3, 4, 5]

for e in arr {

    print(e)

}


Dictionary<Key, Value>형 요소를 for-in문에서 열거하는 경우 요소형은 (Ket, Value) 튜플형이다. 예로 [String: Int]형값을 for-in문에 전달하는 요소는 (String, Int)형이다.


let dic = ["a": 3, "b": 5]

for (key, value) in dic {

    print("키: \(key), 값: \(value)")

}


for-case문은 Sequence프로토콜을 지키는 형요소 중 패턴과 일치하는 것만을 열거하고 반복한다. for-case문은 for-in문 요소 앞에 case키워드를 추가하여 패턴을 설명하는 패터에 일치하는 요소만을 열거한다.


for case 패턴 in 연속값 {

    요소패턴과 일치하는 경우에 실행되는 문장

}


아래 예는 for-in문에서 열거된 요소를 패턴 3 ... 5 평가 요소가 3이상 5이하의 값을 경우에만 { }내 문장을 실행한다.


let arr = [1, 2, 3, 4, 5, 6, 7]

for case 3 ... 5 in arr {

    print("3이상 5이하")

}


while문

while문은 조건식이 성립한 경우에만 반복을 게속 제어한다.


while 조건식 {

    조건식이 성립하는 동안 반복되는 문장

}


while문 조건식은 if문이나 for문처럼 Bool형을 리턴해야 한다. 조건식은 실행문을 실행하기 전에 우선 평가결과가 true이면 반복을 계속한다. false이면 반복을 중지하고 while문 전체 프로세스를 종료한다.


var a = 1

while a < 3 {

    print(a)

    a += 1

}


repeat-while문은 실행문을 실행하기 전에 조건식을 평가하기 위해 경우에 따라 한번도 처리되지않을수도 있다. 즉, 반복횟수는 0회 이상이다. 조건식의 성공여부에 관계없이 반드시 1회이상을 반복을 실행하려는 경우 repeat-while문을 사용한다.


repeat {

    한번은 반드시 실행된 이후에 조건식이 성립하는 경우 반복되는 문장

} while 조건식


while문과 repeat-while문의 실행차이점을 혹인하기 위해 앞에서 예로든 while문의 조건식을 a<1로 변경해 보자. 아마도 아무것도 출력되지 않는다.


var a = 1

while a < 1 {

    print(a)

    a += 1

}


repeat-while문의 경우 처음부터 조건 a<1이 성립되지 않지만, 처음 한번 실행되기 때문에 1이 출력된다.


var a = 1

repeat {

    print(a)

    a += 1

} while a < 1



4. 프로그렘 제어 이동하기

failthrough문

switch문에서 현재 케이스 실행을 종료하고 다음 케이스를 실행하는 제어문이다.


let a = 1

switch a {

    case 1:

        print("1번")

        failthrough

    case 2:

        print("2번")

    default:

        print("기본")

}


C언어를 알고 있는 분이라면 케이스를 실행한 뒤에 다음 케이스가 실행되 것이 기본 실행이지만 Swift언어에서는 failthrough문에 의해 명시적으로 지정하지 않으면 이런 실행은 할 수 없다. 이는 프로그램의 오류로 인한 예기치 못한 실행을 예방하기 위한 것이다.


break문

break문은 switch문의 케이스 실행이나 반복을 중단할 경우에 사용한다. 우선 break문을 사용하여 switch문의 케이스 실행을 중단할 수 있고 guard문을 이용하여 범위에서 빠질 필요가 있거나 케이스내에 처리가 없는 경우에 사용한다. 아래 예는 case 1:에 2개의 print(_:)함수가 있지만, 두번째 print(_:)함수 앞에 break문이 있기 때문에 print(_:)함수는 실행되지 않는다.


let a = 1

switch a {

    case 1:

        print("출력1")

        break

        print("출력2")

    default

        break

}


일반적으로 실행중에 중단할 필요가 없는 경우 break문은 필요하지 않다. 그러나 케이스에는 적어도 하나이상의 실행문이 필요하기 때문에 위의 기본 케이스는 아무것도 하지 않는 처리가 존재하지 않는 경우 break문이 필수적이다.

또한, break문을 사용하여 break문이후의 처리를 생략하고 for문이나 while문에 의한 반복을 중단에도 이용할 수 있다. 예로 조건을 만족하는 경우 나머지 반복을 할 필요가 없는 경우에 이용가능하다.


var a = false

let arr = [1, 2, 3, 4, 5]

for e in arr {

    if e == 2 {

        a = true

        break

    }

    print("요소: \(e)")

}

print("a = \(a)")


continue문

continue문은 continue문 이후의 처리를 생략하는 부분은 break문과 비슷하지만 반복 자체는 계속된다. continue문을 사용하면 for문을 사용하여 배열 요소에 순차적으로 접근할 때 요소가 특정 값인 경우에만 처리를 생략하는등의 처리를 할 수 있다.


var a = Int()

let arr = [1, 2, 3, 4, 5]

for e in arr {

    if e%2 == 2 {

        a.append(e)

        continue

    }

    print("요소: \(e)")

}

print("a = \(a)")


레이블

반복문 if, switch문에 레이블을 지정하여 break문이나 continue문에 의한 제어대상을 세밀하게 조절할 수 있다. 레이블을 사용하면 중첩된 반복에서 한번에 벗어나는 것이 가능하다.

레이블명: 반복문 if문, switch문

레이블 실행을 확인하기 위해 우선 레이블을 사용하는 않는 경우의 실행을 확인하자.


for e in [1, 2, 3, 4, 5] {

    print("e: \(e)")

    for x in [1, 2, 3, 4, 5] {

        print("x: \(x)")

        break

    }

}


첫번째 for문을 break/continue문의 대상으로 첫번째 for문에 레이블을 설정하고 break/continue문의 실행시 레이블을 지정한다. 대상이 되는 반복문에 레이블을 설정하려면  키워드 for, while, repeat문 앞에 레이블명을 만든다. 또한 break문이나 continue문에 레이블을 지정하려면 break/continue키워드 다음에 레이블명을 넣는다.


// for문

label: for e in [1, 2, 3, 4, 5] {

    for x in [1, 2, 3, 4, 5] {

        print("for문")

        break label

    }

}

// while문

label: while true {

    while true {

        print("while문")

        break label

    }

}

// repeat문

label: repeat {

    repeat {

        print("repeat문")

        break label

    } while true

} while true


break, continue문의 기본제어대상은 최근 반복문이지만, 이런 레이블을 추가하여 임의의 반복문을 제어할 수 있다.


5. 지연실행

지연실행은 특정문을 그것이 바로 실행되는 부분보다 나중에 실행되는 것을 의미한다. 여기서 지연실행을 위해서 defer문을 알아보자

defer문에서 { }내의 코드는 defer문이 선언된 범위를 벗어날 때 실행된다. 리소스 해제등 이후의 실행흐름 내용에 관계없이 범위를 벗어나는 것이 확실할 경우 유용하다.


defer {

    defer문이 설명된 범위에서 벗어날 때 실행되는 문장

}


다음 예는 examFunc()함수는 defer문에서 변수 cnt값을 업데이트하고 있다. 값 업데이트는 함수 실행 종료후에 이루어지기 때문에 함수가 값을 리턴하는 시점에서 변수 cnt값은 초기값인 0이다. 따라서, 함수 리턴값은 0이지만, 함수 실행후, 변수 cnt에 접근하면 업데이트된 값을 확인할 수 있다.


var cnt = 0

func examFunc() -> Int {

   defer {

       cnt += 1

   }

   return cnt

}

examFunc() //0

cnt //1



6. 패턴매치

패턴매치는 값의 구조와 설징을 나타내는 패턴에 의한 평가를 하는 것으로 여러가지 종류가 있지만, 자주사용하는 몇가지만 소개한다.


식 패턴

값바인딩 패턴

열거형 케이스 패턴

형캐스팅 패턴


식패턴(Expression pattern)

~= 연산자에 의한 평가를 하는 패턴으로 식패턴은 식만으로 구성된 표현식 ~=평가값이 true를 리턴하는 경우에만 매치된다. ~=연산자에 대한 평가결과 비교 형에 대한 정의가 되어 있기 때문에 독자적으로 ~=평가를 정의할 수 있다. 이 말은

예로 좀더 이해를 해보면, 5 ~= i가 false를 리턴하여 6 ... 9 ~= i가 true를 리턴하는 식패턴 6...9에서 일치한다.


let i = 8

switch i {

    case 5:

        print(" 5일치")

    case 6 ... 9:

        print(" 6~9사이 일치") // 출력됨

    default:

        print("기본값")

}


값바인딩 패턴(Value-binding pattern)

값을 변수와 상수에 할당하기 위한 패턴이다. 값바인딩 패턴은 아래와 같이 var, let키워드와 다른 패턴을 조합된 패턴이 일치하면 값을 할당한다.


//var 키워드 사용하는 경우

var 패턴

//let 키워드 사용하는 경우

let 패턴


값바인딩 패턴과 조합되는 대표적인 패턴은 식별자패턴(Identifier pattern)이다. 식별자 패턴은 변수명 또는 상수명으로 구성되어 어떤 값도 일치한 값을 해당 변수명과 상수명에 할당한다. 값 바인딩 패턴과 결합하면 상수와 변수를 선언하고 할당하는 동작이다. 아래 예에서는 식별자 패턴과 값바인딩 패턴을 조합하여 일치하는 값 5를 상수 s에 대입하고 있다.


let a = 5

switch a {

    case let s:

        print(s)

}


열거형 케이스 패턴(Enumeration case pattern)

이 패턴은 열거형 케이스와 일치할 경우 평가하는 패턴이다. 아래 예는 지구를 반으로 쪼갤 경우, Hemisphere반구를 정의한다면 북반구는 .northern, 남반구는 .southern으로 나뉜다.


enum EarthHemisphere {

    case northern

    case southern

}

let eh = EarthHemisphere.southern

switch eh {

    case .notrhern: 

        print("북반구 일치")

    case .southern:

        print("남반구 일치") //결과출력

}


여기에 열거형 케이스 패턴에 케이스명(패턴, 패턴 ....)형으로 다른 패턴과 결합하면 연상되는 값의 패턴 일치로 처리하는 방법이 있다. 예로 색상값을 받았을 때 처리하는 패턴을 일치된 케이스로 처리하는 방법을 보여준다.


enum Color {

    case rgb(Int, Int, Int)

    case cmyk(Int, Int, Int, Int)

}

let c = Color.rgb(100, 121, 200)

switch c {

    case .rgb(let r, let g, let b)

        print("RGB선택")

    case .cmyk(let c, let m, let y, let k)

        print("CMYK선택")

}


형케스팅 패턴(Type-casting pattern)

형변환에 의한 평가하는 패턴으로 형케스팅패턴은 is연산자로 처리하는 것과 as연산자로 처리하는 것이 있다.

is연산자를 사용한 형케스팅 패턴은 is 형이름으로 선언하고 is연산자에 의한 평가결과가 true이면 일치한다.


let a: Any = 1

switch a {

    case is String:

        print("String 일치")

    case is Int:

        print("Int 일치")

    default:

        print("기본")

}


as 연산자를 사용한 형케스팅 패턴은 다른 패턴과 같이 as 형이름으로 작성한다.이 패턴은 패턴의 식이 다운캐스팅이 되면 일치된다.


let a: Any = 1

switch a {

    case let string as String:

        print("String 일치")

    case let int as Int:

        print("Int 일치") // 출력

    default:

        print("기본")

}


지금까지 제어문에 대해서 정리해보았다. 조건분기문은 guard문으로 나가는 방법이나 switch문의 완전성 컴파일러에 의한 검사를 통해 안전성을 도모했다.즉 제어문은 Swift언어의 특징인 유연성과 안정성이 양립되어 있다는 것이다.












































































매거진의 이전글 2. 변수, 상수 & 기본적인 형들

작품 선택

키워드 선택 0 / 3 0

댓글여부

afliean
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari