1. Associated Values
- 인스턴스가 생성될 때 case에 상수값을 설정할 수 있는데 이 값을 associated values라고 합니다. 아래부터는 연관값이라 표현하겠습니다.
- 연관값은 아래와 같이 타입만 입력해 놓았다가 인스턴스화 할 때 값을 넣어줍니다.
enum Mydog {
case age(Int)
case name(String)
case gender
}
let age : Mydog = .age(4)
let num = 4
let age2 : Mydog = .age(num)
- 연관값을 사용할 때, 연관값이 없는 경우에는 nil을 전달하고 연관값이 있는 경우에는 optional로 값이 전달 됩니다.
- 연관값의 경우에는 == 연산자를 사용할 수 없습니다. 따라서 값 비교를 하고 싶을 경우 Equatuable 프로토콜을 채택해야 합니다.
- 연관값을 불러와서 사용하는 가장 일반적인 방법은 switch문을 사용하는 것입니다.
enum OddOrEven {
case odd(Int)
case even(Int)
}
var number = OddOrEven.even(20)
switch number {
case .odd(let x): print("홀수 :", x)
case .even(let x): print("짝수 :", x)
}
switch number {
case let .odd(x): print("홀수 :", x)
case let .even(x): print("짝수 :", x)
}
2. Enum Initializers
- 생성자를 선언할 때, 반드시 하나의 기본 enum형태를 지정해주어야 하기 때문에 self = ... 형태의 구문이 들어가야 합니다.
enum Filter : String, CaseIterable {
case albums = "Albums"
case playlists = "Playlists"
case podcasts = "Podcasts"
case books = "Audiobooks"
init(_ index:Int) {
self = Filter.allCases[index]
}
}
let type1 = Filter.albums
let type2 = Filter(rawValue:"Playlists")!
let type3 = Filter(2)
- 위의 생성자에는 사실 문제가 있습니다. 만약에 초기화를 할 때 index값에 10이 들어가면 어떻게 될까요? "out of range"라는 런타임 에러가 발생하며 app이 죽게 될 것입니다. 따라서 failable 생성자를 사용해야 합니다.
init?(_ index: Int) {
if !Filter.allCases.indices.contains(index) {
return nil
}
self = Filter.allCases[index]
}
- 참고로, indices의 내용을 모르시는 분들을 위해 Filter.allCases.indices는 Int Range로 0..<4 를 리턴합니다.
- 또한, 혹자는 init?(_ index: Int)을 사용하면 scope내부에 'if !Filter.allCases.indices.contains(index)'가 필요없지 않을까 생각하실 수 있는데, 이런 경우 Filter(10)을 입력할 시 nil을 반환하지 않고 똑같이 out of range 에러가 발생하게 됩니다.
- 생성자는 여러개를 동시에 구현할 수도 있습니다. 위 예시의 let type2 = Filter(rawValue:"Playlists")! 로 인스턴스하는 것에서 param인 rawValue를 생략할 수 있는 생성자를 추가해보겠습니다.
enum Filter : String, CaseIterable {
case albums = "Albums"
case playlists = "Playlists"
case podcasts = "Podcasts"
case books = "Audiobooks"
init?(_ index: Int) {
if !Filter.allCases.indices.contains(index) {
return nil
}
self = Filter.allCases[index]
}
init?(_ rawValue: String) {
self.init(rawValue: rawValue)
}
}
let type1 = Filter.albums
let type2 = Filter(rawValue:"Playlists")!
let type3 = Filter(2)
let type4 = Filter("Audiobooks")!
3. Enum Properties
- enum에는 static property와 computed property가 올 수 있습니다.
- 연산프로퍼티는 enum이 먼저 인스턴스화 되고 난 후에 호출이 가능합니다.
- 타입프로퍼티는 반드시 enum명을 입력하고 호출되어야 합니다.
enum Filter : String, CaseIterable {
case albums = "Albums"
case playlists = "Playlists"
case podcasts = "Podcasts"
case books = "Audiobooks"
static let pod = "Pod"
var sample: SomeFunction {
switch self {
case .albums :
return FistFunction()
default :
return SecondFunction()
}
}
let someFunction = Filter.albums.sample
let someFunction = Filter.sample
let pod = Filter.pod
let pod: Filter = .pod
4. Enum Method - mutating
- 자신의 value를 변경시키는 메서드를 사용할 경우 mutating을 붙여줘야 합니다.
enum Filter : String, CaseIterable {
case albums = "Albums"
case playlists = "Playlists"
case podcasts = "Podcasts"
case books = "Audiobooks"
mutating func advance() {
if self != .playlists {
self = .playlists
}
}
}
var test = Filter.albums
test.advance()
print(test)