代码之家  ›  专栏  ›  技术社区  ›  Mark A. Donohoe

是否可以根据其大小写的名称初始化枚举值(*不是*其原始值?)

  •  0
  • Mark A. Donohoe  · 技术社区  · 8 年前

    考虑此枚举(注意其类型为 Int )

    enum MyTestEnum : Int{
        case one     = 1
        case eight   = 8
        case unknown = -1
    }
    

    您可以根据原始值轻松初始化此版本,如下所示。。。

    let value = MyTestEnum(rawValue:-1)
    

    我试图找出它是否可以用大小写名称本身的字符串表示(同样,不是原始值,而是“case”后面的单词)来初始化,就像这样。。。

    let value = MyTestEnum(caseName:"eight")
    

    注意:我想让它与 任何 枚举(如果可能),无论其原始值类型如何。例如,这个。。。

    enum MyOtherEnum{
        case xxx
        case yyy
        case zzz
    }
    
    let value = MyOtherEnum(caseName:"xxx")
    

    那么这能做到吗?

    思想:

    • 我认为Swift有一种方法可以实例化一个给定字符串的类,该字符串表示完全限定的类名。也许这里可以使用类似的东西。
    4 回复  |  直到 7 年前
        1
  •  9
  •   Mark A. Donohoe    6 年前

    在Swift 4.2中,现在使用 CaseIterable .

    enum MyOtherEnum: CaseIterable {
        case xxx
        case yyy
        case zzz
        
        init?(caseName: String) {
            for value in MyOtherEnum.allCases where "\(value)" == caseName {
                self = value
                return
            }
            
            return nil
        }
    }
    
    enum MyTestEnum: Int, CaseIterable{
        case one     = 1
        case eight   = 8
        case unknown = -1
        
        init?(caseName: String) {
            for value in MyTestEnum.allCases where "\(value)" == caseName {
                self = value
                return
            }
            
            return nil
        }
    }
    

    我在这里所做的是创建一个可失败的初始值设定项,该初始值设定项迭代所有可能的情况,测试是否 "\(value)" (返回该潜在案例的名称)匹配 caseName 参数传递给初始值设定项。

    找到匹配项后, self 设置,循环结束。否则 nil 为调用返回。

    以下是两个工作和两个失败的例子:

    let myOtherEnum = MyOtherEnum(caseName:"xxx")
    print(myOtherEnum) // MyOtherEnum.xxx
    
    let myTestEnum = MyTestEnum(caseName:"eight")
    print(myTestEnum?.rawValue) // 8
    
    let myOtherEnumFail = MyOtherEnum(caseName:"aaa")
    print(myOtherEnumFail) // nil
    
    let myTestEnumFail = MyTestEnum(caseName:"ten")
    print(myTestEnumFail) // nil
    
        2
  •  2
  •   CodeBender    5 年前

    基于CodeBender的 solution 这是这个案子的一个很好的扩展

    extension CaseIterable {
    
        ///Note: case value and name can be different
        init?(caseName: String) {
            for v in Self.allCases where "\(v)" == caseName {
                self = v
                return
            }
            return nil
        }
    }
    
        3
  •  1
  •   Sua Le    8 年前

    您可以使用自定义初始值设定项

    extension MyTestEnum {
        public static func allValues() -> [MyTestEnum] {
            let retVal = AnySequence { () -> AnyIterator<MyTestEnum> in
                var raw = 0
                return AnyIterator {
                    let current = withUnsafePointer(to: &raw) {
                        $0.withMemoryRebound(to: MyTestEnum.self, capacity: 1) { $0.pointee }
                    }
                    guard current.hashValue == raw else { return nil }
                    raw += 1
                    return current
                }
            }
    
            return [MyTestEnum](retVal)
        }
    
        init?(caseName: String){
            for v in MyTestEnum.allValues() {
                if "\(v)" == caseName {
                    self = v
                    return
                }
            }
            self = MyTestEnum.unknown
        }
    }
    
    let test = MyTestEnum(caseName: "eight")
    

    或手动简化所有案例:)

    extension MyTestEnum {
     init?(caseName: String){
       switch caseName {
         case "eight": self.init(rawValue: 8)
         case "one": self.init(rawValue: 1)
         default: self.init(rawValue: -1)
       }
     }
    }
    
    let test1 = MyTestEnum(caseName: "eight") 
    let test2 = MyTestEnum(rawValue: 1)
    

    希望这有帮助!!

        4
  •  -1
  •   andyvn22    8 年前

    听起来您希望枚举案例具有原始 Int 价值观 和 未经加工的 String 价值观严格来说,不可能做到这一点,但也许这很接近:

    enum MyTestEnum : String {
        case one
        case eight
        case unknown
    
        var intValue: Int {
            switch self {
            case one: return 1
            case eight: return 8
            case unknown: return -1
            }
        }
    }
    

    现在可以从案例名称初始化,但也可以检索 intValue 需要时。(如果需要,您可以轻松添加一个可失败的初始值设定项,以允许从整数进行初始化。)