Swift enum with custom initializer loses rawValue initializer

后端 未结 6 1494
长发绾君心
长发绾君心 2021-01-30 12:07

I have tried to boil this issue down to its simplest form with the following.

Setup

Xcode Version 6.1.1 (6A2008a)

An enum defined in MyEnum.swift

相关标签:
6条回答
  • 2021-01-30 12:39
    extension TemplateSlotType {
        init?(rawString: String) {
            // Check if string contains 'carrousel'
            if rawString.rangeOfString("carrousel") != nil {
                self.init(rawValue:"carrousel")
            } else {
                self.init(rawValue:rawString)
            }
        }
    }
    

    In your case this would result in the following extension:

    extension MyEnum {
        init?(string: String) {
            switch string.lowercaseString {
            case "zero": 
                self.init(rawValue:0)
            case "one": 
                self.init(rawValue:1)
            case "two":
                self.init(rawValue:2)
            default: 
                return nil
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-30 12:46

    This works for Swift 4 on Xcode 9.2 together with my EnumSequence:

    enum Word: Int, EnumSequenceElement, CustomStringConvertible {
        case apple, cat, fun
    
        var description: String {
            switch self {
            case .apple:
                return "Apple"
            case .cat:
                return "Cat"
            case .fun:
                return "Fun"
            }
        }
    }
    
    let Words: [String: Word] = [
        "A": .apple,
        "C": .cat,
        "F": .fun
    ]
    
    extension Word {
        var letter: String? {
            return Words.first(where: { (_, word) -> Bool in
                word == self
            })?.key
        }
    
        init?(_ letter: String) {
            if let word = Words[letter] {
                self = word
            } else {
                return nil
            }
        }
    }
    
    for word in EnumSequence<Word>() {
        if let letter = word.letter, let lhs = Word(letter), let rhs = Word(letter), lhs == rhs {
            print("\(letter) for \(word)")
        }
    }
    

    Output

    A for Apple
    C for Cat
    F for Fun
    
    0 讨论(0)
  • 2021-01-30 12:52

    Yeah this is an annoying issue. I'm currently working around it using a global-scope function that acts as a factory, i.e.

    func enumFromString(string:String) -> MyEnum? {
        switch string {
        case "One" : MyEnum(rawValue:1)
        case "Two" : MyEnum(rawValue:2)
        case "Three" : MyEnum(rawValue:3)
        default : return nil
        }
    }
    
    0 讨论(0)
  • 2021-01-30 12:58

    This bug is solved in Xcode 7 and Swift 2

    0 讨论(0)
  • 2021-01-30 12:58

    You can even make the code simpler and useful without switch cases, this way you don't need to add more cases when you add a new type.

    enum VehicleType: Int, CustomStringConvertible {
        case car = 4
        case moped = 2
        case truck = 16
        case unknown = -1
    
        // MARK: - Helpers
    
        public var description: String {
            switch self {
            case .car: return "Car"
            case .truck: return "Truck"
            case .moped: return "Moped"
            case .unknown: return "unknown"
            }
        }
    
        static let all: [VehicleType] = [car, moped, truck]
    
        init?(rawDescription: String) {
            guard let type = VehicleType.all.first(where: { description == rawDescription })
                else { return nil }
            self = type
        }
    }
    
    0 讨论(0)
  • 2021-01-30 13:00

    Add this to your code:

    extension MyEnum {
        init?(rawValue: Int) {
            switch rawValue {
            case 0: self = .Zero
            case 1: self = .One
            case 2: self = .Two
            default: return nil
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题