Joakim Sjöstedt
Joakim Sjöstedt

Reputation: 948

How do I create protocol extensions that work with enums that have been initialized?

I have an enum used in class DoorModeModel:

enum DoorModeName: String {
    case off = "MODE_OFF"
    case exit = "MODE_EXIT"
    case auto = "MODE_AUTO"
    case partial = "MODE_PARTIAL"
    case open = "MODE_OPEN"
}

Then there are two different targets in the app that use different descriptions. I put these in extensions based on target:

extension DoorModeModel.DoorModeName {
    var presentableName: String {
        switch self {
        case .off: return "MODE_OFF".localized()
        case .exit: return "MODE_EXIT".localized()
        case .auto: return "MODE_AUTO".localized()
        case .partial: return "MODE_PARTIAL".localized()
        case .open: return "MODE_OPEN".localized()
        }
    }
}

Then the other extension:

extension DoorModeModel.DoorModeName {
    var presentableName: String {
        switch self {
        case .off: return "MODE_OFF_2".localized()
        case .exit: return "MODE_EXIT_2".localized()
        case .auto: return "MODE_AUTO_2".localized()
        case .partial: return "MODE_PARTIAL_2".localized()
        case .open: return "MODE_OPEN_2".localized()
        }
    }
}

Works great. Then there is a similar, but slightly different enum used in another part of the app, DoorModeService:

enum OperatingModeName: Int {
    case off = 0
    case exit = 1
    case auto = 2
    case partial = 3
    case open = 4   
}

Like before, there are different descriptions based on the target. And like before I created extensions for them. The code is exactly the same as the two extensions above, save for extending a different enum:

extension DoorModeService.OperatingModeName {
    var description: String {
        switch self {
        ...

I don't want duplicate code, so I'm trying to find a way to use the same enum descriptions for both enums. I thought it would be possible to do this using protocol extensions but since the extensions aren't aware of the enums, I don't see how this would work:

protocol EnumDescription {
    var description: String { get }
}

extension EnumDescription {
    var description: String {
        switch self {
        case .off: return "MODE_OFF".localized()
        case .exit: return "MODE_EXIT".localized()
        case .auto: return "MODE_AUTO".localized()
        case .partial: return "MODE_PARTIAL".localized()
        case .open: return "MODE_OPEN".localized()
        }
    }
}

This gives me the error Cannot infer contextual base in reference to member 'x' Do I set the extension to conform to enums, something like:

extension EnumDescription where self == enumSomething

Or how do I go about using the same descriptions for the two enums I have created?

Upvotes: 0

Views: 53

Answers (1)

David Pasztor
David Pasztor

Reputation: 54706

You can create static property requirements with type Self for all common cases between the 2 enums on your protocol to be able to switch over them in the implementation of description.

protocol ModeName: CustomStringConvertible, Equatable {
    static var off: Self { get }
    static var exit: Self { get }
    static var auto: Self { get }
    static var partial: Self { get }
    static var open: Self { get }
}

extension ModeName {
    var description: String {
        switch self {
        case .off: return "MODE_OFF".localized()
        case .exit: return "MODE_EXIT".localized()
        case .auto: return "MODE_AUTO".localized()
        case .partial: return "MODE_PARTIAL".localized()
        case .open: return "MODE_OPEN".localized()
        default:
            return ""
        }
    }
}

enum DoorModeName: String, ModeName {
    case off = "MODE_OFF"
    case exit = "MODE_EXIT"
    case auto = "MODE_AUTO"
    case partial = "MODE_PARTIAL"
    case open = "MODE_OPEN"
}

enum OperatingModeName: Int, ModeName {
    case off = 0
    case exit = 1
    case auto = 2
    case partial = 3
    case open = 4   
}

Upvotes: 1

Related Questions