> For the complete documentation index, see [llms.txt](https://lochiwei.gitbook.io/ios/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://lochiwei.gitbook.io/ios/swift/debugging/casereflectable.md).

# CaseReflectable

{% tabs %}
{% tab title="👔 CaseReflectable" %}
💾 程式：[paiza.io](https://paiza.io/projects/BgeXldbalSZcvt3C_5qcQg)    ⬆️ 需要： [Mirror](/ios/swift/debugging/mirror.md), [HasMirrors](/ios/swift/debugging/hasmirrors.md)

```swift
// --------------------------
//     ⭐ CaseReflectable
// --------------------------

// designed for enums only (use it on other types not recommended)
public protocol CaseReflectable: Loggable {
    /// log enum case (default implementation provided)
    func logEnumCase() -> Self
}

// ⭐ default behavior.
extension CaseReflectable {
    
    /// ⭐ case name
    public var caseName: String {
        let mirror = Mirror(reflecting: self)
        // enum cases:
        // - normal case: no children
        // - case with associated values: one child (with label)
        guard let label = mirror.children.first?.label else {
            return "\(self)"    // normal case
        }
        // ase with associated values
        return label
    }
    
    /// ⭐ associated values
    public var associatedValues: Any? {
        // if no children, a normal case, no associated values.
        guard let firstChild = Mirror(reflecting: self).children.first else {
            return nil
        }
        // return associated values
        return firstChild.value
    }
    
    /// ⭐ log enum case
    @discardableResult
    public func logEnumCase() -> Self {
        if let values = self.associatedValues {
            print("case: .\(caseName), values: \(values), type: \(type(of: values))")
        } else {
            print("case: .\(caseName) (no associated values)")
        }
        return self
    }
}

// -----------------------------
//     ⭐ custom operator ~=
// -----------------------------

/// match enum cases with associated values, while disregarding the values themselves.
/// usage: `Enum.enumCase ~= instance`
public func ~= <Enum: CaseReflectable, AssociatedValue>(
    // an enum case (with associated values)
    enumCase: (AssociatedValue) -> Enum,    // enum case as function
    // an instance of Enum
    instance: Enum
) -> Bool 
{
    // if no associated values, `instance` can't be of `enumCase`
    guard let values = instance.associatedValues else { return false }
    // if associated values not of the same type, return false
    guard values is AssociatedValue else { return false }
    // create an instance from `enumCase` (as function)
    let case2 = enumCase(values as! AssociatedValue)
    // if same case name, return true
    return case2.caseName == instance.caseName
}
```

{% endtab %}

{% tab title="💈範例" %}
💾 程式：[paiza.io](https://paiza.io/projects/BgeXldbalSZcvt3C_5qcQg)    ⬆️ 需要： 👔 CaseReflectable

```swift
// enum with associated values
enum Rank {
    case number(Int)
    case jack, queen, king
    case ace(suit: Character)
    case range(min: Int, max: Int)
}

// ⭐ enum cases
let cases: [Rank] = [ 
    .jack, 
    // jack
    // Main.Rank.jack
    // no children
    .number(7), 
    // number(7)
    // Main.Rank.number(7)
    // • number: 7 (Int)
    .ace(suit: "♠️"),
    // ace(suit: "♠️")
    // Main.Rank.ace(suit: "♠️")
    // • ace: (suit: "♠️") ((suit: Character))]
    .range(min: 3, max: 8),
    // range(min: 3, max: 8)
    // Main.Rank.range(min: 3, max: 8)
    // • range: (min: 3, max: 8) ((min: Int, max: Int))
]

// 👔 Loggable
cases.forEach { $0.log().reflect().mirror() }

// 👔 CaseReflectable (case name, associated values)
cases.forEach { $0.logEnumCase() }
// case: .jack (no associated values)
// case: .number, values: 7, type: Int
// case: .ace, values: (suit: "♠️"), type: (suit: Character)
// case: .range, values: (min: 3, max: 8), type: (min: Int, max: Int)
```

{% endtab %}

{% tab title="📗 參考" %}

* [x] SwiftLee ⟩ [Reflection in Swift: How Mirror works](https://www.avanderlee.com/swift/reflection-how-mirror-works/)  ⭐️ (inspiration)
* [ ] iJoshSmith ⟩ [Reflectable enums in Swift 3](https://ijoshsmith.com/2017/04/08/reflectable-enums-in-swift-3/)
  {% endtab %}

{% tab title="🗣 討論" %}

* [how to use `if case` statement as boolean in swift](https://stackoverflow.com/questions/67189140/how-to-use-if-case-statement-as-boolean-in-swift) (inspiration from [Jessy](https://stackoverflow.com/a/67204360/5409815))
* [How to filter array of enums with associated values?](https://stackoverflow.com/questions/30973826/how-to-create-a-predicate-to-filter-array-of-enums-with-associated-values-in-swi/70827654#70827654)
  {% endtab %}

{% tab title="👥 相關" %}

* [enum case pattern](/ios/swift/pattern-matching/enum-case-pattern.md) - pattern matching
* [operator (\~=)](/ios/swift/pattern-matching/operator.md) - pattern matching
* [Mirror](/ios/swift/debugging/mirror.md) - required struct.
  {% endtab %}

{% tab title="⬆️ 需要" %}

* [Mirror](/ios/swift/debugging/mirror.md)
* [HasMirrors](/ios/swift/debugging/hasmirrors.md)
  {% endtab %}

{% tab title="⬇️ 應用" %}

* [filter cases](/ios/swift/type/category/basic/enum/filter-cases.md)
  {% endtab %}
  {% endtabs %}
