简体   繁体   中英

Swift - Associated value or extension for an Enum

General question regarding swift enum.

I want to create an enum of "icon" and "associate" a value to the enum case

enum Icon {
  case plane
  case arrow
  case logo
  case flag
}

I want to create an associated image to the enum's value. And also an associated color to the enum value

So for instance if it was possible to do something like:

extension Icon.plane {
  var image = {
    get {
       return UIImage("plane.png")
    }
  }
  var color = {
    get {
       return UIColor.greenColor()
    }
  }
}


var image = Icon.arrow.image // the image associated to the enum
var color = Icon.arrow.color // the color associated to the enum

Is this type of thing possible?

Unfortunately you cannot define static properties based on enum cases, but you can use computed properties and switch to return values for each case:

enum Icon {
    case plane
    case arrow
    case logo
    case flag

    var image: UIImage {
        switch self {
            case .plane: return UIImage(named: "plane.png")!
            case .arrow: return UIImage(named: "arrow.png")!
            case .logo: return UIImage(named: "logo.png")!
            case .flag: return UIImage(named: "flag.png")!
        }
    }

    var color: UIColor {
        switch self {
        case .plane: return UIColor.greenColor()
        case .arrow: return UIColor.greenColor()
        case .logo: return UIColor.greenColor()
        case .flag: return UIColor.greenColor()
        }
    }
}

// usage
Icon.plane.color

Using enums with associated values combined with switch statements you can be very flexible. A first example:

enum Icon {
    case plane(img:UIImage, col:UIColor)
    case arrow(img:UIImage, col:UIColor)
    case logo(img:UIImage, col:UIColor)
    case flag(img:UIImage, col:UIColor)

    var values:(img:UIImage,col:UIColor) {
        switch self {
        case let .plane(image, color):
            return (image,color)
        case let .arrow(image, color):
            return (image,color)
        case let .logo(image, color):
            return (image,color)
        case let .flag(image, color):
            return (image,color)
        }
    }
}



var a = Icon.plane(img: UIImage(named: "image.png")!, col: UIColor.blueColor())

a.values.col
a.values.img

and a second example:

enum Icon {
    case plane(img:UIImage, col:UIColor)
    case arrow(img:UIImage, col:UIColor)
    case logo(img:UIImage, col:UIColor)
    case flag(img:UIImage, col:UIColor)

    var img:UIImage {
        switch self {
        case let .plane(image, color):
            return image
        case let .arrow(image, color):
            return image
        case let .logo(image, color):
            return image
        case let .flag(image, color):
            return image
        }
    }

    var col:UIColor {
        switch self {
        case let .plane(image, color):
            return color
        case let .arrow(image, color):
            return color
        case let .logo(image, color):
            return color
        case let .flag(image, color):
            return color
        }
    }
}



var a = Icon.plane(img: UIImage(named: "image.png")!, col: UIColor.blueColor())

a.col
a.img

no need for extensions. And if you really do want static values, you could do this:

struct MyIcon {
    static let plane = Icon.plane(img: UIImage(named: "image.png")!, col: UIColor.blueColor())
    static let arrow = Icon.arrow(img: UIImage(named: "image.png")!, col: UIColor.blueColor())
    static let logo = Icon.logo(img: UIImage(named: "image.png")!, col: UIColor.blueColor())
    static let flag = Icon.flag(img: UIImage(named: "image.png")!, col: UIColor.blueColor())
}

MyIcon.arrow.col

which might be tidier than placing the fixed literal values inside a switch statement.

Shorter and safer code:

import UIKit

enum Icon: String {

    case plane, arrow, logo, flag

    var image: UIImage {

        // If the image is not available, provide a default value so we dont force optional unwrapping
        return UIImage(named: "\(self.rawValue).png") ?? UIImage()
    }

    var color: UIColor {
        switch self {
        case .plane: return UIColor.green
        case .arrow: return UIColor.green
        case .logo: return UIColor.green
        case .flag: return UIColor.green
        }
    }
}

// Usage
Icon.plane.color
Icon.arrow.image

More cleaner and readable

enum Icon {
    case plane
    case arrow
    case logo
    case flag

    var image: UIImage {
        return value.image
    }

    var color: UIColor {
        return value.color
    }

    private var value: (image: UIImage, color: UIColor) {
        switch self {
        case .plane: return (UIImage(named: "plane.png")!, UIColor.green)
        case .arrow: return (UIImage(named: "arrow.png")!, UIColor.green)
        case .logo: return (UIImage(named: "logo.png")!, UIColor.green)
        case .flag: return (UIImage(named: "flag.png")!, UIColor.green)
        }
    }
}

// Use
Icon.plane.image
Icon.plane.color

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM