OptionSet을 준수하는 커스텀 타입 작성하기

OptionSet 이란

OptionSet은 Enum 타입과 유사하지만 한 번에 둘 이상의 상태를 나타낼 수 있습니다.

OptionSet 프로토콜을 준수하여 비트 마스킹이 가능하고 개별 비트 집합을 표현할 수 있습니다.

참고로 문서에 따르면 Apple SDK의 300개 이상의 타입에서 사용되고 있습니다.

 

서브 뷰의 autoresizing을 적용하려는 상황을 가정해보겠습니다.

subview.autoresizingMask = []
subview.autoresizingMask = .flexibleTopMargin
subview.autoresizingMask = [.flexibleLeftMargin, .flexibleTopMargin]

 

OptionSet은 SetAlgebra 프로토콜을 준수하기 때문에 Set 자료형의 형태로 초기화할 수 있습니다.

 

UIView.AutoresizingMask는 다음과 같이 구현되어 있습니다.

public struct AutoresizingMask : OptionSet {

    public init(rawValue: UInt)

    
    public static var flexibleLeftMargin: UIView.AutoresizingMask { get }

    public static var flexibleWidth: UIView.AutoresizingMask { get }

    public static var flexibleRightMargin: UIView.AutoresizingMask { get }

    public static var flexibleTopMargin: UIView.AutoresizingMask { get }

    public static var flexibleHeight: UIView.AutoresizingMask { get }

    public static var flexibleBottomMargin: UIView.AutoresizingMask { get }
}

 

각 프로퍼티의 rawValue는 다음과 같습니다.

- flexibleLeftMargin.rawValue == 1 (000001)
- flexibleWidth.rawValue == 2 (000010)
- flexibleRightMargin.rawValue == 4 (000100)
- flexibleTopMargin.rawValue == 8 (001000)
- flexibleHeight.rawValue == 16 (010000)
- flexibleBottomMargin.rawValue == 32 (100000)

OptionSet을 구현하기 위해서는 FixedWidthInteger protocol을 준수하는 rawValue(Int 또는 UInt8)를 정의되어야 합니다.

또한, OptionSet을 준수하는 타입의 프로퍼티는 static으로 정의되고 고유의 단일 비트 값(1,2,4,8,16,32 ..)으로 표현되어야 합니다.

 

OptionSet을 준수하는 커스텀 타입 작성

 

리눅스의 파일 권한을 예로 들어 Permission 타입을 구현하였습니다.

기본적으로 실행하기/쓰기/읽기 권한 프로퍼티가 있으며 

유저(파일을 실행하고 읽을 수 있을 수 있음), 관리자(실행하기/읽기/쓰기)가 있습니다.

 

struct Permission: OptionSet {
    let rawValue: UInt
    
    static let executable = Permission(rawValue: 1 << 0)
    static let writable   = Permission(rawValue: 1 << 1)
    static let readable   = Permission(rawValue: 1 << 2)
    
    static let user: Permission = [.executable, .readable]
    static let admin: Permission = [.executable, .writable, .readable]
}

각 프로퍼티의 rawValue는 다음과 같습니다.

- executable.rawValue == 1 (001)
- writable.rawValue == 2 (010)
- readable.rawValue == 4 (100)

- user.rawValue == 5 (101)
- admin.rawValue == 7 (111)

1. OptionSet 프로토콜을 준수하는 새로운 구조체를 정의합니다.

2. FixedWidthInteger 프로토콜을 준수하는 Int 또는 UInt8 타입의 rawValue 인스턴스 프로퍼티를 정의합니다.

3. bit shifting을 사용하여 2의 거듭 제곱 수 (1,2,4,8..)를 rawValue로 갖는 정적 프로퍼티를 정의합니다.

 

참고자료

www.donnywals.com/understanding-swifts-optionset/

medium.com/@ahmadfayyas/swift-more-elegant-code-optionset-205e4866b4aa

dev.classmethod.jp/articles/about-option-set/

'iOS' 카테고리의 다른 글

iOS File System  (0) 2021.04.04
NSCache와 Purgeable Memory  (0) 2021.04.02
Render loop 정리 (작성중)  (0) 2021.03.28
CustomStringConvertible  (0) 2021.03.27
[UIKit] Scrollable StackView 만들기  (0) 2021.03.26

댓글