"Raw Value for Enum Case Is Not Unique" for Swift Enum with Float Raw Values

Raw value for enum case is not unique for Swift enum with Float raw values

It definitely says you can, but don't use floating-point values (and especially Float) where you're going to need to compare equality -- the precision just isn't guaranteed to be good enough. And always use Double unless you absolutely need to use a Float for compatibility reasons.

In this case, it seems like it's having trouble because (a) the third case is 2x the first case, and (b) some other factor I don't know. Using 3.3/6.6, 3.4/6.8, and 3.6/7.2 also gave me the issue, but 3.5/7.0 did not. However, I could get it to show up by changing the last case to 22.2 (2x 11.1).

Here's a workaround — use a typical Int-based enumeration, and provide a doubleValue property:

enum BatteryVoltage: Int {
case v3v7
case v5v0
case v7v4
case v11v1
case v12v0

var doubleValue: Double {
switch self {
case .v3v7: return 3.7
case .v5v0: return 5.0
case .v7v4: return 7.4
case .v11v1: return 11.1
case .v12v0: return 12.0
}
}
}

There are some nice additional features of enums you can take advantage of if they're Int-based.

Swift enum cannot assign default raw value

In (Objective-)C an enumeration defines a set of named integer constants, and those need not be distinct:

enum {
A = 1,
B = 2,
C = 99,
Default = B
};

The cases of a Swift enum represent mutually distinct values, and their raw values – if assigned – must be unique:

enum BestLetters: Int {
case a = 1
case b
case c
case `default` = 2 // Error: Raw value for enum case is not unique
}

On the other hand, enumerations in Swift are first-class types, so that you can define a static property for that purpose:

enum BestLetters {
case a
case b
case c
static let `default` = BestLetters.b
}

(This is also how Swift imports C enumerations with duplicate values, compare touchIDLockout deprecated in iOS 11.0.)

Enum multiple cases with the same value in Swift

Swift doesn't support duplicated values (or "aliases" semantically). If you don't mind, you can mimic it by using something like this:

enum Foo: Int {
case Bar = 0

static var Baz:Foo {
get {
return Bar
}
}
static var Jar:Foo {
get {
return Foo(rawValue: 0)!
}
}
}

With recent version of Swift, this can be shortened like this:

enum Foo: Int {
case bar = 0

static var baz:Foo { .bar }
static var jar:Foo { Foo(rawValue: 0)! }
}

Note that Swift has changed their naming convention of enum variants from PascalCase to camelCase.

Swift enum raw value: not working with CGFloat = -1.0

That sounds like a bug. However it seems to work if you omit the decimal part:

enum Aspect : CGFloat {
case Clockwise = 1
case Anticlockwise = -1
}

How to declare enums in Swift of a particular class type?

From Docs

In particular, the raw-value type must conform to the Equatable
protocol and one of the following protocols:
ExpressibleByIntegerLiteral for integer literals,
ExpressibleByFloatLiteral for floating-point literals,
ExpressibleByStringLiteral for string literals that contain any number
of characters, and ExpressibleByUnicodeScalarLiteral or
ExpressibleByExtendedGraphemeClusterLiteral for string literals that
contain only a single character.

So make your class Abc to conform to Equatable and one of the above mentioned protocols. Here is an example

public class Abc : Equatable,ExpressibleByStringLiteral{
var age = 25
var name = "Abhi"
public static func == (lhs: Abc, rhs: Abc) -> Bool {
return (lhs.age == rhs.age && lhs.name == rhs.name)
}
public required init(stringLiteral value: String) {
let components = value.components(separatedBy: ",")
if components.count == 2 {
self.name = components[0]
if let age = Int(components[1]) {
self.age = age
}
}
}
public required convenience init(unicodeScalarLiteral value: String) {
self.init(stringLiteral: value)
}
public required convenience init(extendedGraphemeClusterLiteral value: String) {
self.init(stringLiteral: value)
}
}

enum TestEnum : Abc {
case firstCase = "Jack,29"
case secondCase = "Jill,26"
}

Now you can initialize your enum like

let exEnum = TestEnum.firstCase
print(exEnum.rawValue.name) // prints Jack

For detailed discussion and example you can refer
https://swiftwithsadiq.wordpress.com/2017/08/21/custom-types-as-raw-value-for-enum-in-swift/

How to access a Swift enum associated value outside of a switch statement

As others have pointed out, this is now kind of possible in Swift 2:

import CoreGraphics

enum Line {
case Horizontal(CGFloat)
case Vertical(CGFloat)
}

let min = Line.Horizontal(0.0)
let mid = Line.Horizontal(0.5)
let max = Line.Horizontal(1.0)

func doToLine(line: Line) -> CGFloat? {
if case .Horizontal(let value) = line {
return value
}
return .None
}

doToLine(min) // prints 0
doToLine(mid) // prints 0.5
doToLine(max) // prints 1


Related Topics



Leave a reply



Submit