dub
dub

Reputation: 491

Get enum from matching associated value

How do I select an enum that's associated value as a UIImage matches a UIImage?

enum ClothingType: String {
    case head
    case body
    case pants

    var imageForClothingType: UIImage {
        switch self {
        case .head: return #imageLiteral(resourceName: "hatsicon")
        case .body: return #imageLiteral(resourceName: "bodyicon")
        case .pants: return #imageLiteral(resourceName: "pantsicon")
        }
    }
}

I want to select the corresponding ClothingType from the button that gets pressed:

@IBAction func chooseClothingType (_ sender: UIButton) {

    let theImage: UIImage = sender.currentImage!
    let matchingType: ClothingType = theImage
    confirmClothingType(type: matchingType)
}

func confirmClothingType (type: ClothingType) {
    // perform needed function
}

Upvotes: 0

Views: 60

Answers (2)

Callam
Callam

Reputation: 11539

I would subclass UIButton and create a property to set the ClothingType.

class ClothingButton: UIButton {
    var type: ClothingType? {
        didSet {
            setImage(type?.imageForClothingType, for: .normal)
        }
    }
}

class ClothingViewController: UIViewController {
    @IBAction func chooseClothingType (_ sender: ClothingButton) {
        print(sender.type.debugDescription)
    }
}

Upvotes: 0

Ricky Mo
Ricky Mo

Reputation: 7618

By doing so, you are violating the philosophy of MVC and the point of using enum. You should use the enum, which is a much simpler data object, for all the underlying operations, and only render the image when displaying, and never read the image back since you should already know its underlying enum value on behalf of the image.

I would set the tag attribute for the UIButton and make the enum inherit Int. Let say you have 3 UIButton, then set their tags to 0,1,2(or their clothingType.rawValue programatically) respectively. You can then retrieve the enum with the following implementation:

enum ClothingType: Int {
    case head = 0
    case body = 1
    case pants = 2

    var imageForClothingType: UIImage {
        switch self {
        case .head: return #imageLiteral(resourceName: "hatsicon")
        case .body: return #imageLiteral(resourceName: "bodyicon")
        case .pants: return #imageLiteral(resourceName: "pantsicon")
        }
    }
}

@IBAction func chooseClothingType (_ sender: UIButton) {

    if let matchingType: ClothingType = ClothingType(rawValue: sender.tag)
    {
        confirmClothingType(type: matchingType)
    }
}

Upvotes: 2

Related Questions