代码之家  ›  专栏  ›  技术社区  ›  Paul B

具有符合CaseIterable、RawRepresentable的关联值的枚举

  •  0
  • Paul B  · 技术社区  · 7 年前

    我正在尝试使具有关联值的枚举符合casiterable和rawrepresentable。当使用rawvalue初始化时,我可以使用一些关联值的默认值。

    enum GenresAssociated: CaseIterable, RawRepresentable, Equatable {
        case unknown(String)
        case blues(String)
        case classical(String)
        // Implementing CaseIterable
        typealias AllCases = [GenresAssociated]
        // Enums can have no storage, but the class they are in CAN. Note 'static' in declaration
        static var allCases: [GenresAssociated] = [.unknown(""), .blues(""), .classical("")]
    
    
        typealias RawValue = Int
        var rawValue: Int {
    
            // MARK: This causes a crash for unknown reason
            return GenresAssociated.allCases.firstIndex(where: {  if case self = $0 { return true } else { return false } } ) ?? 0
        }
        init?(rawValue: Int) {
            guard GenresAssociated.allCases.indices.contains(rawValue) else { return nil }
            self = GenresAssociated.allCases[rawValue]
        }
    }
    

    是否有任何方法可以在所有情况下不手动切换,即没有这样的代码:

        typealias RawValue = Int
        var rawValue: Int {
            switch self {
            case .unknown:
                return 0
            case .blues:
                return 1
            case .classical:
                return 2
            }
        }
    

    值得注意的是,非常相似的代码工作得很好,例如

    enum EnumWithValue {
        case one(NSString!), two(NSString!), three(NSString!)
    }
    
    let arrayOfEnumsWithValues: [EnumWithValue] = [.one(nil), .two(nil), .three("Hey")]
    
    if let index = arrayOfEnumsWithValues.firstIndex(where: { if case .two = $0 { return true }; return false }) {
        print(".two found at index \(index)") //prints ".two found at index 1"
    }
    
    0 回复  |  直到 7 年前
        1
  •  2
  •   J. Doe    7 年前

    我终于找到了工作 Mirror 啊!

    var rawValue: Int {
        let selfCaseName = Mirror(reflecting: self).children.first!.label!
    
        return GenresAssociated.allCases.firstIndex(where: { (genre) in
            let switchingCaseName = Mirror(reflecting: genre).children.first!.label!
    
            return switchingCaseName == selfCaseName
        })!
    }
    

    别介意拆开包装,这里很安全。