티스토리 뷰

programming/Swift

[Swift/iOS] 열거형(1)

마들브라더 2022. 10. 8. 21:24

열거형

  • 추가/수정이 불가능
  • 제한된 선택지를 주고 싶을 때
  • 정해진 값 외에는 입력받고 싶지 않을 때
  • 예상된 입력 값이 한정되어 있을 때
  • 값을 가질 수도 가지지 않을 수도 있음
    • 각 항목이 그 자체로 고유의 값이 될 수 있음
    • 원시값(raw value) 형태로 실제 값을 가질 수 도 있음
    • 연관 값(associated values)을 사용하여 공용체라고 불리는 값의 묶음도 구현 가능

기본 열거형

  • 열거형의 선언, 할당, 변경
enum School {
    case primary
    case elementary
    case middle
    case high
    case college
    case university
    case graduate
}

enum car {
    case bus, taxi, car, truck
}

// 값 할당하고 변경하기
var highestEducationLevel: School = School.university
highestEducationLevel = .university
highestEducationLevel = .graduate // 같은 타입의 내부 항목으로만 변경 가능

원시값

  • 각 항목은 자체로도 하나의 값이지만 원시 값도 가질 수 있음(raw value)
  • 특정 타입으로 지정된 값을 가질 수 있음
  • rawValue라는 프로퍼티를 통해 가져올 수 있음
enum School: String {
    case primary = "유치원"
    case elementary = "초등학교"
    case middle = "중학교"
    case high = "고등학교"
    case college = "대학"
    case university // 원시값은 university
    case graduate // 원시값은 graduate
}

enum WeekDays: Character {
    case mon = "월", tue = "화", wed = "수", thu = "목", fri = "금", sat = "토", sun = "일"
}

enum Number: Int {
    case zero // 0
    case one = 1
    case two = 2
    case three // 3
    case ten = 10
    case eleven // 11
}

// 원시 값을 안다면 원시 값을 통해 열거형의 변수 또는 상수를 생성해줄 수 있음
// 올바르지 않은 원시값이면 nil 반환
let primary = School(rawValue: "유치원") // primary
print(primary) // Optional(__lldb_expr_17.School.primary)
let graduate = School(rawValue: "석박사") // nil

연관 값

  • 열거형 내의 항목(case)이 자신과 연관된 값을 가질 수 있음
  • 각 항목 옆에 소괄호로 묶어서 표현
enum MainDish {
    case pasta(taste: String)
    case pizza(dough: String, topping: String)
    case chicken(withSauce: Bool)
    case rice
}

var dinner: MainDish = .pasta(taste: "크림")
dinner = .pizza(dough: "치즈크러스트", topping: "불고기")
dinner = .chicken(withSauce: true)
dinner = .rice
  • 여러 열거형의 응용
enum PastTaste {
    case cream, tomato
}
enum PizzaDough {
    case cheeseCrust, thin, original
}
enum PizzaTopping {
    case pepperoni, cheese, bacon
}

enum MainDish {
    case pasta(taste: PastTaste)
    case pizza(dough: PizzaDough, topping: PizzaTopping)
    case chicken(withSauce: Bool)
    case rice
}

var dinner: MainDish = .pasta(taste: .tomato)

항목 순회

  • CaseIterable 프로토콜을 채택, allCases라는 타입 프로퍼티를 통해 모든 케이스의 컬렉션을 생성가능
enum School: CaseIterable {
    case primary
    case elementary
    case middle
    case high
    case college
    case university
    case graduate
}

let allCases = School.allCases
print(allCases) // [__lldb_expr_21.School.primary, __lldb_expr_21.School.elementary, __lldb_expr_21.School.middle, __lldb_expr_21.School.high, __lldb_expr_21.School.college, __lldb_expr_21.School.university, __lldb_expr_21.School.graduate]
  • 원시값을 닺는 열거형의 항목 순회
enum School: String, CaseIterable {
    case primary = "유치원"
    case elementary = "초등학교"
    case middle = "중학교"
    case high = "고등학교"
    case college = "대학"
    case university = "대학교"
    case graduate = "대학원"
}

let allCases = School.allCases
print(allCases) // [__lldb_expr_24.School.primary, __lldb_expr_24.School.elementary, __lldb_expr_24.School.middle, __lldb_expr_24.School.high, __lldb_expr_24.School.college, __lldb_expr_24.School.university, __lldb_expr_24.School.graduate]
  • CaseIterable 프로토콜을 채택하는 것만으로는 allCases를 사용할 수 없는 경우
    • available 속성을 갖는 열거형의 항목 순회
enum School: String, CaseIterable {
    case primary = "유치원"
    case elementary = "초등학교"
    case middle = "중학교"
    case high = "고등학교"
    case college = "대학"
    case university = "대학교"
    @available(iOS, obsoleted: 12.0)
    case graduate = "대학원"

    static var allCases: [School] {
        let all: [School] = [.primary, .elementary, .middle, .high , .college, .university]
        #if os(iOS)
        return all
        #else
        return all + [.graduate]
        #endif
    }
}

let allCases: [School] = School.allCases
print(allCases) // 실행환경에 따라 다른 결과
  • 연관 값을 갖는 경우에도 CaseIterable 채택 만으로 allCases 사용불가능
댓글