PM Extra
PM Extra

Reputation: 435

Swift 3: How to map between enums according to the same name?

enum PtzButton: Int {
    case play = 1
    case up = 2
    case stop = 3
    case left = 4
    case none = 5
    case right = 6
    case zoomIn = 7
    case down = 8
    case zoomOut = 9

    internal static let ptzActionMap: [PtzButton: PtzAction] = [
        .up: .up,
        .down: .down,
        .left: .left,
        .right: .right,
        .zoomIn: .zoomIn,
        .zoomOut: .zoomOut
    ]

    var ptzAction: PtzAction? {
        return PtzButton.ptzActionMap[self]
    }
}

The PtzAction is a model enum. The PtzButton is a view bind enum. They are very similar, but the PtzButton have more than cases. It have to be aware, they has different rawValue definition, and I shouldn't change them.

So, my problem is that: Is there a better way to simplify the ptzActionMap code?

I guess these repeated codes is so wordy:

        [.up: .up,
        .down: .down,
        .left: .left,
        .right: .right,
        .zoomIn: .zoomIn,
        .zoomOut: .zoomOut]

Upvotes: 5

Views: 4605

Answers (2)

vadian
vadian

Reputation: 285069

I'd use a switch expression:

enum PtzButton: Int {
    case play = 1, up, stop, left, none, right, zoomIn, down, zoomOut

    var ptzAction: PtzAction? {
        switch self {
        case .up: return .up
        case .down: return .down
        case .left: return .left
        case .right: return .right
        case .zoomIn: return .zoomIn
        case .zoomOut: return .zoomOut
        default : return nil
        }
    }
}


let button = PtzButton.right
if let action = button.ptzAction {
    print(action.rawValue)
}

Alternatively map the raw values:

enum PtzAction : Int {
    case up = 1, down, left, right, zoomIn, zoomOut
}

enum PtzButton: Int {
    case play = 1, up, stop, left, none, right, zoomIn, down, zoomOut

    static let actionRawValues = [0, 1, 0, 3, 0, 4, 5, 2, 6]
}

let button = PtzButton.down
let actionRaw = PtzButton.actionRawValues[button.rawValue - 1] // zero based index
if let action = PtzAction(rawValue: actionRaw) {
    print(action.rawValue)
}

Upvotes: 7

Jordan Smith
Jordan Smith

Reputation: 10378

At first sight, I'd probably think about approaching this slightly differently.

Enum cases in Swift can contain values. The following seems elegant - although may or may not suit what you'd like to do.

enum Action {
    case up, down, left, right, zoomIn, zoomOut
}

enum Button {
    case forAction(Action)
    case play, stop, none
}

Upvotes: 1

Related Questions