# OptionSet

{% hint style="info" %}
* 如果變數的行為像「<mark style="color:red;">**單選題**</mark>」，可考慮用 [enum](../type/category/basic/enum)。
* 如果類似「<mark style="color:red;">**多選題**</mark>」，可考慮用 <mark style="color:orange;">**OptionSet**</mark>。
{% endhint %}

{% tabs %}
{% tab title="⭐️ 使用" %}
{% hint style="info" %}
When creating an <mark style="color:red;">**option set**</mark>, include a <mark style="color:purple;">**`rawValue`**</mark> property in your type <mark style="color:red;">**declaration**</mark>. For your type to automatically receive <mark style="color:red;">**default implementations**</mark> for <mark style="color:red;">**set-related operations**</mark>, the <mark style="color:purple;">**`rawValue`**</mark>property must be of a type that conforms to the <mark style="color:purple;">**`FixedWidthInteger`**</mark> protocol, such as <mark style="color:purple;">**`Int`**</mark>or <mark style="color:purple;">**`UInt8`**</mark>.&#x20;
{% endhint %}

```swift
struct ShippingOptions: OptionSet {
    // ⭐️ required property
    let rawValue: Int    // ⭐️ conforms to 🅿️ FixedWidthInteger
}
```

{% hint style="info" %}
Next, create unique options as <mark style="color:red;">**static properties**</mark> of your custom type using <mark style="color:red;">**unique powers of two**</mark> (1, 2, 4, 8, 16 ...) for each individual property’s raw value so that each property can be represented by a <mark style="color:orange;">**single bit**</mark> of the type’s raw value.
{% endhint %}

```swift
struct ShippingOptions: OptionSet {

    let rawValue: Int

    // ⭐️ unit sets (containing only one element)
    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)

    // ⭐️ useful sets (containing multiple elements)
    // ⭐️ can be initialized by array literal (ExpressibleByArrayLiteral)
    static let express: ShippingOptions = [.nextDay, .secondDay]
    static let all: ShippingOptions = [.express, .priority, .standard]
}

// ⭐️ empty set
let noOptions: ShippingOptions = []
```

{% hint style="warning" %}
⭐️ 注意：**OptionSet** 的 methods 雖然看起來像是元素與集合間的用語 (源自於 [SetAlgebra](https://developer.apple.com/documentation/swift/setalgebra))，但要注意每個 OptionSet 的 <mark style="color:red;">**static properties**</mark> 本質上還是一個「集合」的概念，就算只包含一個元素都是如此！
{% endhint %}

```swift
var A: ShippingOptions = []
let B: ShippingOptions = .priority

// ⭐️ 雖然以下是集合與元素間的用語，但 A 跟 B 其實都是集合喔！
A.insert(B)
A.contains(B)
```
{% endtab %}

{% tab title="💈範例" %}
{% hint style="success" %}
* [dimensionpositions](../../swiftui/view/view/.dimension/dimensionpositions "mention") - used by [.dimension](../../swiftui/view/view/.dimension "mention") to decorate views.
* [logger](../debugging/logger "mention") - <mark style="color:purple;">**Logger.TableOptions**</mark> is an **OptionSet**.
{% endhint %}

#### Other examples:

```swift
let price = 87
var options: ShippingOptions = []

if price > 50 { options.insert(.priority) }
if options.contains(.priority) { ... } 
```
{% endtab %}

{% tab title="📜 協定" %}
![](https://1830103165-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M5-JmwCZMKh_d7RfBaN%2F-MPgdSxzl4ZlLkH8dj7W%2F-MPgdZmlEpSardd2Th8C%2FSetAlgebra.png?alt=media\&token=95e9931a-cac9-44b5-9806-cba07c0c2b14)
{% endtab %}

{% tab title="📗 參考" %}
* [x] [How to solve problems with bitwise operators in Swift](https://tanaschita.com/posts/20201214-working-with-bits-in-swift/) - Natascha Fadeeva
* [x] [Singleton (mathematics)](https://en.wikipedia.org/wiki/Singleton_\(mathematics\)) - Wikipedia
* [x] [Understanding Swift’s OptionSet](https://www.donnywals.com/understanding-swifts-optionset/) - Donny Wals
* [x] [OptionSet](https://nshipster.com/optionset/) - NSHipster
* [x] [Swift, more elegant code: OptionSet](https://medium.com/@ahmadfayyas/swift-more-elegant-code-optionset-205e4866b4aa) - Ahmad Fayyas
{% endtab %}

{% tab title="📘 手冊" %}
* Swift  ⟩  Standard Libary  ⟩  [Collections](https://developer.apple.com/documentation/swift/swift_standard_library/collections)  ⟩ &#x20;
  * [OptionSet](https://developer.apple.com/documentation/swift/optionset)
  * [SetAlgebra](https://developer.apple.com/documentation/swift/setalgebra)
{% endtab %}

{% tab title="👥 相關" %}
* [.dimension](../../swiftui/view/view/.dimension "mention") - use **OptionSet** to help **decorate** views.
{% endtab %}
{% endtabs %}
