[SWIFT] OptionSet

2021. 3. 7. 16:30SWIFT

반응형

Swift의 Collections 타입 중에 OptionSet이라는 타입에 대해 작성해보려고 합니다.

저도 사용해본 적은 없지만, 사용해보면 좋겠다는 생각이 들어서 공부를 하고 정리를 하게되었습니다.

 

 

OptionSet란

OptionSet은 비트의 집합으로 자료구조 중에서 Set의 특징을 가지고 있는 자료구조입니다. Apple 개발자 문서를 보아도 Collections > Set으로 분류가 되어 있습니다. 

 

비트의 집합으로 구성된다는 뜻은 만약 0000의 4비트가 존재한다면 각각의 비트가 하나의 옵션을 나타낸다는 뜻입니다. 지금은 이정도만 이해를 하고 넘어가고 뒤에 실제 예시를 통해 이해하면 될 것 같습니다.

(즉, 각 옵션에 대해서 1, 2, 4, 8, 16의 값을 가지게 될 것입니다..!!)

 

그렇다면 이 타입은 언제 사용하면 좋을까요??

OptionSet의 이름만 보고는 어떤 느낌이 오시나요. 뭔가 여러개의 옵션이 있고 이것들의 집합(?)이라는 느낌이 직감적으로 오시지 않나요.

 

그리고 비트들의 집합이라고 했죠..? 합쳐보면 결국 비트들이 어떤 옵션하나를 나타내고 이것들의 집합을 비트로 나타낸 것이라고 할 수 있을 것 같습니다.

 

Swift에서 enum 타입이 있는데, 만약 여러개의 옵션을 가져야하는 값이 있다면 이 OptionSet을 이용하면 더욱 좋을 것 같습니다.

 

그렇다면, 한 번 예시를 보면서 이해해보겠습니다.

struct ShippingOptions: OptionSet {
    let rawValue: Int

    static let nextDay    = ShippingOptions(rawValue: 1 << 0)
    static let secondDay  = ShippingOptions(rawValue: 1 << 1)
    static let priority   = ShippingOptions(rawValue: 1 << 2)
    static let standard   = ShippingOptions(rawValue: 1 << 3)

    static let express: ShippingOptions = [.nextDay, .secondDay]
    static let all: ShippingOptions = [.express, .priority, .standard]
}

우선 OptionSet 기본적으로 rawValue 값을 가지고 있습니다.

이 값이 바로 이 OptionSet의 어떤 옵션이 들어있는지를 비트 연산의 결과로 가지고 있는 값입니다.

 

여기서 우선 nextDay, secondDay, priority, standard와 같이 4가지의 옵션을 확인할 수 있습니다. (밑의 2가지는 나중에 별도로 보겠습니다.)

 

각각의 옵션에 대해 rawValue: 1 << 0로 초기화를 진행시켜주고 있는데, <<연산자가 바로 비트 연산자입니다. 

1이라는 값에 대해 왼쪽으로 0번 시프트 하겠다는 뜻인데 그러면 결국 1의 값은 1이 되겠죠?

즉, nextDay라는 값은 1이라는 값을 가지는 옵션이 되는 것입니다.

 

그렇다면 secondDay는 어떨까요?

1이라는 값에 왼쪽으로 1번 시프트 연산을 했습니다. 

즉, 2라는 값을 가지는 secondDay 옵션이 된 것입니다.

 

priority 역시 1이라는 값이 왼쪽으로 2번의 시프트를 실행했습니다.

4라는 값을 가진느 priority 옵션이 되었습니다.

 

standard는 3번 시프트를 실행했기 때문에, 8이라는 값을 가지는 옵션이 된 것입니다.

 

어때요..? 여기까지는 이해가 되시나요?

아까 위에서 enum 타입인데, 각각의 옵션을 비트 집합으로 표현할 수 있는 타입이라고 설명한게 조금은 와닿나요?

 

이제 마지막으로 밑의 express, all 옵션을 살펴보겠습니다.

OptionSet은 비트의 집합이라고 했습니다!!

 

그렇다면 현재 expressnextDay, secondDay라는 옵션을 가지고 있습니다.

비트의 값은 어떻게 될까요.

 

nextDay = 1, secondDay = 2입니다. 이를 각각 비트로 나타내면 어떨까요?

nextDay = 0001, secondDay = 0010 입니다.

 

이 둘을 합치면 express가 되는데, express는 결국 0011이 되는 것입니다.

즉, 10진수의 값으로 나타내면 3이 되는 것이죠..!!

 

이렇게 비트의 집합으로 고유한 옵션을 가지는 OptionSet을 만들 수 있는 것입니다.

 

그렇다면 이 값을 어떻게 활용할 수 있을까요?

 

여러분들이 자료구조의 Set에서 얻을 수 있는 이점은 합집합, 차집합, 포함관계와 관련된 연산들을 편하게 할 수 있었는데, 당연히 OptionSet도 Set의 종류로서 이런 연산들을 모두 할 수 있습니다.

 

예시를 통해 보겠습니다~~!!

let singleOption: ShippingOptions = .priority
let multipleOptions: ShippingOptions = [.nextDay, .secondDay, .priority]
let noOptions: ShippingOptions = []

singleOption.rawValue      // 4
multipleOptions.rawValue   // 7
noOptions.rawValue         // 0

우선 각 값은 이런식으로 할당을 할 수 있습니다. 

 

이제 이 값들을 활용해서 포함관계, 삽입 등의 연산을 해보겠습니다~~!!

let purchasePrice = 87.55

var freeOptions: ShippingOptions = []
if purchasePrice > 50 {
    freeOptions.insert(.priority)
}

if freeOptions.contains(.priority) {
    print("You've earned free priority shipping!")
} else {
    print("Add more to your cart for free priority shipping!")
}

이렇게 ShippingOptions 타입을 만들어주고 원하는 옵션이 있으면 insert 연산을 통해 추가할 수 있고, 만약 포함관계가 알고 싶으면 contain 연산을 이용해서 분기처리를 할 수 있을 것 같습니다.

 

 

오늘은 이렇게 OptionSet 타입에 대해서 알아보았습니다.

아직도 모르는게 많은 것 같은데 OptionSet을 이용해서 좀 더 언어를 고급적으로 사용할 수 있을 것 같습니다.

도움이 되었으면 좋겠네요 :)

반응형

'SWIFT' 카테고리의 다른 글

[SWIFT] Metatype - self, Self, Type  (0) 2021.03.21
[SWIFT] Property Wrapper  (0) 2021.03.14
[SWIFT] Swift SOLID 원칙  (0) 2021.02.27
[SWIFT] defer 후처리  (0) 2021.02.16
[SWIFT] Set  (0) 2021.01.28