나의 발자취

열거형과 switch문 본문

앱 개발/iOS

열거형과 switch문

달모드 2022. 6. 3. 00:04

열거형에 대한 구체적인 처리는 스위치문과 함께 쓸 때 사용성이 높아진다.

열거형한정된 사례로 만든 타입이고, 스위치문은 표현식에 대한 분기처리에 최적화 되어 있기 때문에 활용에 적합하다.

 

// 로그인 타입을 정의

 

enum LoginProvider: String {      // 3가지로 정의

    case email

    case facebook

    case google

}

 

let userLogin = LoginProvider.facebook

 

switch userLogin {                   // 3가지로 분기처리

case .email:

    print("이메일 로그인")

case .facebook:

    print("페이스북 로그인")

case .google:

    print("구글 로그인")

}

 

 

 

 

// 물론 특정한 경우도 처리 가능

if LoginProvider.email == userLogin {

    print("이메일 로그인")

}

 

 

1. 열거형에 연관값이 없고, 옵셔널 열거형의 경우

// 열거형의 선언

enum SomeEnum {

    case left

    case right

}

 

// 타입을 다시 옵셔널 열거형으로 선언 ⭐️

let x: SomeEnum? = .left

 

 

/**==================================================

 [SomeEnum?의 의미] 옵셔널 열거형

 

 - 값이 있는 경우 .some ===> 내부에 다시 열거형 .left /.right 이 정의되어있는 상태

 - 값이 없는 경우 .none ===> nil

=====================================================**/

 

-> 열거형 안에 열거형이 있는 경우다! 

// 원칙적으로는, 두 번 옵셔널 해제를 해주어야한다.

switch x {

case .some(let value):      // Optional.some(let value) = Optional.some(SomeEnum.left)  ⭐️

    switch value {

    case .left:

        print("왼쪽으로 돌기")

    case .right:

        print("오른쪽으로 돌기")

    }

case .none:

    print("계속 전진")

}

 

 

하지만, 너무 불편하기 때문에!

// 편의적 기능 제공 ⭐️ -> 바인딩을 할 필요 없이 아예 괄호 안에다가 써서 동시에 벗길 수 있도록 하는 방법!

 

switch x {

case .some(.left):

    print("왼쪽으로 돌기")

case .some(.right):

    print("오른쪽으로 돌기")

case .none:

    print("계속 전진")

}

대신, 열거형에 연관값이 없어야 한다.

 

// 전체적으로 full name으로 풀어서 쓴다면..

switch x {

case Optional.some(SomeEnum.left):

    print("왼쪽으로 돌기")

case Optional.some(SomeEnum.right):

    print("오른쪽으로 돌기")

case Optional.none:

    print("계속 전진")

}

 

스위치문의 편의성

-> switch문에서 옵셔널 열거형 타입을 사용할때, 벗기지 않아도 내부값 접근가능

// 스위치문은 옵셔널 열거형 타입의 사용시, 편의성을 제공

switch x {     // 예전에는 x! 라고 써줘야 했음 (스위치문에서 옵셔널 타입도 ok)

case .left:

    print("왼쪽으로 돌기")

case .right:

    print("오른쪽으로 돌기")

case nil:

    print("계속 전진")

}

결국 스위치문은 옵셔널을 쉽게 사용하는 기능을 제공한다.

 

 

 

2. 열거형에 연관값이 있는 경우

1) 연관값(Associated Values)이 있는 경우와 switch문 (열거형 case 패턴) - Enumeration Case Pattern

 

 

/**==========================================

 - 연관값이 있는 열거형의 활용 (열거형 case 패턴) ⭐️

 - 구체적 정보(연관값)를 변수에 바인딩(let/var가능)하는 패턴

 

 [열거형 case 패턴]

 - case Enum.case(let 변수이름):

 - case let Enum.case(변수이름):

 

 [스위치문 뿐만 아니라, 조건문/반복문에서도 활용가능]

 - 1) switch문 (대부분)

 - 2) if / guard / for-in / while (필요한 경우)

 ===========================================**/

 

// 연관값이 있는 열거형 - 구체적인 정보가 연관값에 들어 있음

// 구체적인 정보를 꺼내서 사용해야하는, 로직 구현의 문제와 연관

enum Computer {                         // 3가지로 정의

    case cpu(core: Int, ghz: Double)

    case ram(Int, String)

    case hardDisk(gb: Int)

}

 

var chip = Computer.cpu(core: 8, ghz: 3.1)

 

 

switch chip {                          // 수십가지로도 처리 가능 (필요한 처리 확장 가능)

case .cpu(core: 8, ghz: 3.1):

    print("CPU 8코어 3.1GHz입니다.")

case .cpu(core: 8, ghz: 2.6):

    print("CPU 8코어 2.6GHz입니다.")

case .cpu(core: 4, ghz: let ghz):       // let ghz = 연관값  (cpu가 4코어인 경우, ghz에 저장된 연관값을 꺼내서 바인딩)

    print("CPU 4코어 \(ghz)HGz입니다.")

case .cpu(core: _, ghz: _):

    print("CPU 칩 입니다.")

case .ram(32, _):

    print("32기가램 입니다.")

case .ram(_, _):

    print("램 입니다.")

case let .hardDisk(gb: gB):            // let gB = 연관값

    print("\(gB)기가 바이트 하드디스크 입니다.")

default:                               // 대부분 default문이 필요하기도 함

    print("그 외에 나머지는 관심이 없습니다. 그렇지만 칩이긴 합니다.")

}

 

 

// 연관값을 가지고 있는 열거형의 경우, 원하는 로직으로 잘 정의해서 처리해야하는 것에 주의

 

2) 연관값(Associated Values)이 있는 경우, if / guard / for-in / while 문 (열거형 case 패턴)

 

 

// 값 하나를 사용하기 위해서, 스위치문을 전체를 다 써야하는 불편함이 있었음

 

switch chip {

case Computer.hardDisk(gb: let gB):      // let gB = 연관값

    print("\(gB)기가 바이트 하드디스크임")

default:

    break

}

 

위와 동일. 

if 문에서도 case 활용이 가능하다. 이럴 때는 스위치문에서 콜론을 쓰는것과는 다르게 등호로 할당을 해주어야한다.

 

if case Computer.hardDisk(gb: let gB) = chip {

    print("\(gB)기가 바이트 하드디스크임")

}

 

//:> 특정 케이스만 다루기 위해서 if문이나 반복문(for문) 사용 가능

 

chip = Computer.hardDisk(gb: 128)    // 256

 

 

 

// if문에서도 스위치문에서 사용하는 case문과 같이 사용 가능 ⭐️

 

if case Computer.hardDisk(gb: let gB) = chip {

    print("\(gB)기가 바이트 하드디스크임")

}

 

 

if case Computer.hardDisk(gb: let gB) = chip, gB == 256 {    //  if 문에서는 콤마를 쓰고 여러개의 조건문을 사용 가능.

    print("256기가 바이트 하드디스크임")

}

 

 

 

let chiplists: [Computer] = [

    .cpu(core: 4, ghz: 3.0),

    .cpu(core: 8, ghz: 3.5),

    .ram(16, "SRAM"),

    .ram(32, "DRAM"),

    .cpu(core: 8, ghz: 3.5),

    .hardDisk(gb: 500),

    .hardDisk(gb: 256)

]

 

 

for case let .cpu(core: c, ghz: h) in chiplists {    // 배열중에서 특정 케이스만 뽑아서 활용 가능 ⭐️

    print("CPU칩: \(c)코어, \(h)헤르츠")

}

 

=> CPU 케이스인 경우만 출력됨.

 

// 일반 for문과 비교 =====> 모든 경우가 출력

 

for chip in chiplists {

    print("\(chip)")

}

 

 

열거형 케이스 패턴(for문) - 옵셔널타입 요소 배열

// 옵셔널 타입을 포함하는 배열에서 반복문을 사용하는 경우, 배열문 내부에 nil 인 경우도 다룰 수 있음.

 

let arrays: [Int?] = [nil, 2, 3, nil, 5]

 

 

for case .some(let number) in arrays {  // some에 해당하는 경우만 사용하겠다=nil 은 버림

    print("Found a \(number)")

}

// 출력결과는 2,3,5만 나온다.

 

 

 

 

'앱 개발 > iOS' 카테고리의 다른 글

@unknown 키워드  (0) 2022.06.25
옵셔널  (0) 2022.06.25
옵셔널 타입의 내부 구조  (0) 2022.05.27
열거형  (0) 2022.05.27
컬렉션 관련 이론: KeyValuePairs, Copy-On-Write 최적화  (0) 2022.05.26
Comments