【问题标题】:Using reflection to reduce enum boilerplate?使用反射来减少枚举样板?
【发布时间】:2019-08-27 05:16:28
【问题描述】:

最近,我发现了这个方便的小 sn-p 代码来获取枚举的字符串表示,即使存在关联值:

enum XXX {
    case a
    case b
    case c(Int)

    private var typeStr: String {
        guard let label = Mirror(reflecting: self).children.first?.label else { 
            return .init(describing: self) 
        }
        return label
    }
}

这很聪明。反射也可以用来减少像这个 init 函数这样的样板文件吗?

init?(rawValue: String?)
{
    guard let val = rawValue?.lowercased() else {
        return nil
    }
    switch val {
        case "a", "1a": self = .a
        case "b", "1b": self = .b
        case "c", "1c": self = .c(1)
        default: return nil
    }
}

【问题讨论】:

  • 我认为 Mirror 无法做到这一点。

标签: ios swift xcode reflection enums


【解决方案1】:

要通过 rawValue 使用 init,您需要符合 RawRepresentable。遵循CaseIterable 是个好主意,因为我们需要一组allCases

enum SomeEnum: CaseIterable, RawRepresentable{
    case a
    case b
    case c(Int)

    typealias AllCases = [SomeEnum]
    static let allCases: [SomeEnum] = [.a, .b, .c(0)]
    static let allCasesStr = { SomeEnum.allCases.map{ $0.typeStr } }
    typealias RawValue = String

    var rawValue: String {
        return self.typeStr
    }

    init?(rawValue: String) {
        let allCasesStrLocal = SomeEnum.allCasesStr()
        let allCasesLocal = SomeEnum.allCases
        print(allCasesStrLocal)
        guard let i = allCasesStrLocal.firstIndex(of: rawValue), allCasesLocal.indices.contains(i)  else { return nil }
            print(i)
            self = allCasesLocal[i]
        }

    private var typeStr: String {
        guard let label = Mirror(reflecting: self).children.first?.label else {
            return .init(describing: self)
        }
        return label
    }
}

// Tests
let caseA = SomeEnum.a
let caseAWithRawInit = SomeEnum.init(rawValue: "a")!
let caseBWithRawInit = SomeEnum.init(rawValue: "b")!
let caseC = SomeEnum.c(123)
let caseCWithRawInit = SomeEnum.init(rawValue: "c")!
print(caseA, caseAWithRawInit, caseBWithRawInit, caseC, caseCWithRawInit)
// "a a b c(123) c(0)\n"

在 Playground (Xcode 10) 中运行良好。您可以尝试避免使用一些本地变量(allCasesStrLocalallCasesLocal)和额外的分配,但可能会有一些问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-06-27
    • 1970-01-01
    • 1970-01-01
    • 2016-07-13
    • 1970-01-01
    • 2019-10-29
    • 1970-01-01
    • 2012-12-12
    相关资源
    最近更新 更多