Swift enums

I've defined some special colours like this:


enum Colors {
  case blue, white
}

let MyColors: Dictionary<Colors, SKColor> = [
  .blue: SKColor(red: 0.29, green: 0.47, blue: 0.647, alpha: 1.0),
  .white: SKColor(red: 0.98, green: 0.98, blue: 1.0, alpha: 1.0)]


But I still don't fully understand how Swift enums work. Is there a more direct way of doing this with an enum?


dkj

Is there a more direct way of doing this with an enum?

No. As far as I know.


Swift enums can have associated values, but this may not be what you intend:

enum MyColor {
    case color(red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat)

    static let blue = color(red: 0.29, green: 0.47, blue: 0.647, alpha: 1.0)
    static let white = color(red: 0.98, green: 0.98, blue: 1.0, alpha: 1.0)
}

or simpley:

enum MySKColor {
    case color(SKColor)
  
    static let blue = color(SKColor(red: 0.29, green: 0.47, blue: 0.647, alpha: 1.0))
    static let white = color(SKColor(red: 0.98, green: 0.98, blue: 1.0, alpha: 1.0))
}

In both enums above, blue and white are not enum-cases. Very similar to just defining global constants.


Swift enums can have rawValues, but you cannot use tuples or classes for rawValue type.

You can write something like this:

enum IntColor: Int {
    case blue = 0x5A78A5FF
    case white = 0xFAFAFFFF
}

Seems to be less direct.


Your code seems to be a good example utilizing Swift enum.

I don't think the enum + dictionary gets you anything on top of using a tuple:

let _PALETTE_EMOJI = (
  blue: SKColor(red: 0.29, green: 0.47, blue: 0.647, alpha: 1.0),
  white: SKColor(red: 0.98, green: 0.98, blue: 1.0, alpha: 1.0)
)


EDIT: THIS IS INCORRECT because UIColor is "immutable", in that it has no mutating accessors, so you'd never be able to change it anyway. I'm leaving this idea here so that you can learn that you were also wrong if you had the same idea I did.

However, SKColor is UIColor, which is a class, which is not appropriate for color usage. Until Sprite Kit has transitioned to SIMD types, you should probably return new instances every time.

struct PALETTE_EMOJI {
  static var blue: SKColor {
    return SKColor(red: 0.29, green: 0.47, blue: 0.647, alpha: 1.0)
  }
  static var white: SKColor {
    return SKColor(red: 0.98, green: 0.98, blue: 1.0, alpha: 1.0)
  }

  private init() {}
}


As this is a frequently-used data structure, I think Emoji is more appropriate than English, but this forum can't display emoji.


I also think we can expect the next version of Xcode proper to do away with colors represented by numbers in code. Instead, we'll have editable swatches, as are used in the Unity Editor (but not its accompaying C#). Playgrounds almost have this already.

I was looking for something that would let me write simple things like:


myView.backgroundColor = MyColor.blue


So defining a global tuple gives me just what I want:


let MyColor = (
  blue: SKColor(red: 0.29, green: 0.47, blue: 0.647, alpha: 1.0),
  white: SKColor(red: 0.98, green: 0.98, blue: 1.0, alpha: 1.0))


But the enum with static constants works equally well, with only one extra line of code:


enum MyColor {
  case color(SKColor)
  static let blue = SKColor(red: 0.29, green: 0.47, blue: 0.647, alpha: 1.0)
  static let white = SKColor(red: 0.98, green: 0.98, blue: 1.0, alpha: 1.0)}


Is there any reason to prefer one over the other?

Your way of providing type members as colors seems to be a good way so this is a little bit off topic and a little too detailed, but this description:

you should probably return new instances every time.

is not appropriate.


UIColor Class Reference

Color objects are immutable and so it is safe to use them from multiple threads in your app.


It is clearly stated the safety of using color objects from mutilple threads, which means you have no need to create new instances every time.

Wow! Thanks for the info! What a terrible data structure!

Accepted Answer

I would go with:


public enum MyColor {
  static let blue = SKColor(red: 0.29, green: 0.47, blue: 0.647, alpha: 1.0)
  static let white = SKColor(red: 0.98, green: 0.98, blue: 1.0, alpha: 1.0)
}


Note no cases, they aren't needed and add nothing most of the time for examples like this (but see below for exception). The enum is used as a namespace, since enum is the nearest Swift has to a namespace (you will see it used like this in the standard library).


If you want to switch on the color and have the compiler check all cases and not have to add default then you might choose:


public enum MyColor {
 case blue
 case white
 var value: SKColor {
   switch self {
   case .blue:
     return blueValue
   case .white:
     return whiteValue
   }
 }
  private static let blueValue = SKColor(red: 0.29, green: 0.47, blue: 0.647, alpha: 1.0)
  private static let whiteValue = SKColor(red: 0.98, green: 0.98, blue: 1.0, alpha: 1.0)
}

I am having problems translating legacy systems enums from Objective C to Swift.


The Swift compiler keeps giving me "unidentied identifier errors for kCGImageAlphaPremultipliedFirst and kCGBlendModeNormal in the following code:


cacheContext = CGBitmapContextCreate(cacheBitmap, size.width * scaleFactor, size.height * scaleFactor, 8, bitmapBytesPerRow,
CGColorSpaceCreateDeviceRGB(), kCGImageAlphaPremultipliedFirst)

CGContextSetBlendMode(cacheContext, kCGBlendModeNormal)


Does one have to include/import any special files to fix this, or is my syntax at fault?


Any help would be greatly appreciated.

Thanks,


Shiraz

The enums provided by the system frameworks in the current SDK are a little inconsistent at the moment (but iOS 10 SDK should bring some improvement, I hope). Anyway, try this:

cacheContext = CGBitmapContextCreate(cacheBitmap, size.width * scaleFactor, size.height * scaleFactor, 8, bitmapBytesPerRow, CGColorSpaceCreateDeviceRGB(), CGImageAlphaInfo.PremultipliedFirst.rawValue)
CGContextSetBlendMode(cacheContext, .Normal)

Thanks for the prompt response. That got rid of the relevant error messages. Now I need to get rid of my other syntax errors to confirm.

Swift enums
 
 
Q