Binary tree implementation using Swift enum - swift

I'm doing some experiments with Swift enums to become more familiarized with them and have implemented a rudimentary binary tree. It works when adding up to three items, but adding more beyond that doesn't change it and I couldn't see why it wasn't working.
Here's the code:
protocol TreeProtocol {
mutating func insert(value: Int)
func walk()
}
enum Tree:TreeProtocol {
case Empty
case Leaf(Int)
case Node(Int, TreeProtocol?, TreeProtocol?)
init(){
self = .Empty;
}
init(value: Int) {
self = .Leaf(value)
}
init(value: Int, left:TreeProtocol?, right:TreeProtocol?){
self = .Node(value, left, right);
}
mutating func insert(value: Int) {
switch self {
case .Empty:
self = .Leaf(value)
case .Leaf(let currentNodeValue):
let newTree = Tree(value: value) // var here generates a warning
if value < currentNodeValue {
self = .Node(currentNodeValue, newTree, .None)
}
else {
self = .Node(currentNodeValue, .None, newTree)
}
case let .Node(currentNodeValue, leftNode, rightNode):
if (value < currentNodeValue) {
if leftNode == nil {
let newTree = Tree(value: value)
self = .Node(currentNodeValue, newTree, rightNode)
}
else {
var l = leftNode! // unable to call leftNode!.insert() directly
l.insert(value)
}
}
else {
if rightNode == nil {
let newTree = Tree(value: value)
self = .Node(currentNodeValue, leftNode, newTree)
}
else {
var r = rightNode!
r.insert(value)
}
}
}
}
func walk() {
switch self {
case .Empty:
print("Empty")
case .Leaf (let value):
print("\(value), ")
case .Node(let value, let leftNode, let rightNode):
if leftNode != nil {
leftNode!.walk()
}
print("\(value) ")
if (rightNode != nil) {
rightNode!.walk()
}
}
}
}
And if I run the following tests:
var tree = Tree();
tree.walk()
tree.insert(100)
tree.walk()
tree.insert(50)
tree.walk()
tree.insert(150)
tree.walk()
tree.insert(25)
tree.walk()
The output is:
Empty
100
50,
100
50,
100,
150
50,
100,
150
The 25 value is not getting added to the tree
(This code is a bit inelegant, its just the first iteration, there's several ugly parts in there that could be improved and beautified. Waiting for recursive enum functionality to be added to the Xcode beta).

Because you're mutating the internal nodes and that is actually creating a copy of them. That copy is never inserted into the tree, it's just thrown away after being modified. If after inserting into l and r you reinsert those nodes (with self = .Node(currentNodeValue, l, rightNode) and self = .Node(currentNodeValue, leftNode, r) respectively) then the tree as a whole will get updated. It's a by-value / by-reference issue.

I know you already have an answer, but I really like your implementation and thought I'd provide the code for implementing #Wain's solution and also streamline some of the nested if-else logic.
It involves a slight modification for the protocol, so that insert returns a value:
protocol TreeProtocol {
mutating func insert(value: Int) -> TreeProtocol
func walk()
}
And then the insert function can be rewritten like this:
mutating func insert(value: Int) -> TreeProtocol {
switch self {
case .Empty:
self = .Leaf(value)
case .Leaf(let currentNodeValue):
let newTree = Tree(value: value)
self = value < currentNodeValue
? .Node(currentNodeValue, newTree, .None)
: .Node(currentNodeValue, .None, newTree)
case var .Node(currentNodeValue, leftNode, rightNode):
self = value < currentNodeValue
? .Node(currentNodeValue, leftNode?.insert(value) ?? Tree(value: value), rightNode)
: .Node(currentNodeValue, leftNode, rightNode?.insert(value) ?? Tree(value: value))
}
return self
}

Related

Accessing decodable enum after parsing in SwiftUI [duplicate]

In this code I've written a really useless enum that defines a possible Number with Int or Float.
I can't understand how can I access the value that I set with the association. If I try to print it I get just (Enum Value)
enum Number {
case int (Int)
case float (Float)
}
let integer = Number.int(10)
let float = Number.float(10.5)
println("integer is \(integer)")
println("float is \(float)")
For sake of completeness, enum's association value could be accesed also using if statement with pattern matching. Here is solution for original code:
enum Number {
case int (Int)
case float (Float)
}
let integer = Number.int(10)
let float = Number.float(10.5)
if case let .int(i) = integer {
print("integer is \(i)")
}
if case let .float(f) = float {
print("float is \(f)")
}
This solution is described in detail in: https://appventure.me/2015/10/17/advanced-practical-enum-examples/
The value is associated to an instance of the enumeration. Therefore, to access it without a switch, you need to make a getter and make it available explicitly. Something like below:
enum Number {
case int(Int)
case float(Float)
func get() -> NSNumber {
switch self {
case .int(let num):
return num
case .float(let num):
return num
}
}
}
var vInteger = Number.int(10)
var vFloat = Number.float(10.5)
println(vInteger.get())
println(vFloat.get())
Maybe in the future something like that may be automatically created or a shorter convenience could be added to the language.
It surprises me that Swift 2 (as of beta 2) does not address this. Here's an example of a workaround approach for now:
enum TestAssociatedValue {
case One(Int)
case Two(String)
case Three(AnyObject)
func associatedValue() -> Any {
switch self {
case .One(let value):
return value
case .Two(let value):
return value
case .Three(let value):
return value
}
}
}
let one = TestAssociatedValue.One(1)
let oneValue = one.associatedValue() // 1
let two = TestAssociatedValue.Two("two")
let twoValue = two.associatedValue() // two
class ThreeClass {
let someValue = "Hello world!"
}
let three = TestMixed.Three(ThreeClass())
let threeValue = three. associatedValue() as! ThreeClass
print(threeValue.someValue)
If your enum mixes cases with and without associated values, you'll need to make the return type an optional. You could also return literals for some cases (that do not have associated values), mimicking raw-value typed enums. And you could even return the enum value itself for non-associated, non-raw-type cases. For example:
enum TestMixed {
case One(Int)
case Two(String)
case Three(AnyObject)
case Four
case Five
func value() -> Any? {
switch self {
case .One(let value):
return value
case .Two(let value):
return value
case .Three(let value):
return value
case .Four:
return 4
case .Five:
return TestMixed.Five
}
}
}
let one = TestMixed.One(1)
let oneValue = one.value() // 1
let two = TestMixed.Two("two")
let twoValue = two.value() // two
class ThreeClass {
let someValue = "Hello world!"
}
let three = TestMixed.Three(ThreeClass())
let threeValue = three.value() as! ThreeClass
print(threeValue.someValue)
let four = TestMixed.Four
let fourValue = four.value() // 4
let five = TestMixed.Five
let fiveValue = five.value() as! TestMixed
switch fiveValue {
case TestMixed.Five:
print("It is")
default:
print("It's not")
}
// Prints "It is"
like #iQ. answer, you can use property in enum also
enum Number {
case int (Int)
var value: Int {
switch self {
case .int(let value):
return value
}
}
}
let integer = Number.int(10)
println("integer is \(integer.value)")
I have used something like this:
switch number {
case .int(let n):
println("integer is \(n)")
case .float(let n):
println("float is \(n)")
}
If you're using guard, you can write like below:
enum Action {
case .moveTab(index: Int)
}
guard let case .moveTab(index) = someAction else { return }
You can access enum associated value not only through switch! Mirrors come to our aid
Let's create a protocol
protocol MirrorAssociated {
var associatedValues: [String: Any] { get }
}
extension MirrorAssociated {
var associatedValues: [String: Any] {
var values = [String: Any]()
if let associated = Mirror(reflecting: self).children.first {
let children = Mirror(reflecting: associated.value).children
for case let item in children {
if let label = item.label {
values[label] = item.value
}
}
}
return values
}
}
and use it like this:
enum Test: MirrorAssociated {
case test(value: String, anotherValue: Int)
}
Now we can access any associated value without using switch:
let test: Test = .test(value: "Test String", anotherValue: 1337)
if let value = test.associatedValues["value"] as? String {
print("\(value)") // "Test String"
}
if let intValue = test.associatedValues["anotherValue"] as? Int {
print("\(intValue)") // 1337
}
Swift 5
enum Directory {
case accountImages(URL)
case accountData(URL)
var url: URL {
switch self {
case .accountImages(let url):
return url
case .accountData(let url):
return url
}
}
}
func save(to directory: Directory) {
let dir = directory.url
}
Swift 4,
I have created a simple enum with associated values for handling firebase database reference paths
import Firebase
enum FirebaseDBConstants {
case UserLocation(database : DatabaseReference, userID :String)
case UserRequest(database : DatabaseReference, requestID :String)
func getDBPath() -> DatabaseReference {
switch self {
case .UserLocation(let database,let userID):
return database.root.child(FirebaseDBEnvironmentEnum.getCurrentEnvioronMent()).child("Location").child(userID).child("JSON")
case .UserRequest(let database,let requestID):
return database.root.child(FirebaseDBEnvironmentEnum.getCurrentEnvioronMent()).child("Request").child(requestID)
default:
break
}
}
}
Use it like as shown
//Pass Database refenence root as parameter with your request id
let dbPath = FirebaseDBConstants.UserRequest(database: database, requestID: requestId).getDBPath()

Swift Recursion/ Class constructors

I am writing a Swift program that will solve post script equations. I have two Classes: ExpressionTree, and ExpressionTreeLeaf, which inherits Expression Tree. In the ExpressionTree Class, I need a method that solves the tree. I also need to override that function in the ExpressionTreeLeaf Class to just return the data of the leaf. I'll give some code for context:
ExpressionTree class:
class ExpressionTree{
let Left: ExpressionTree?
let Right: ExpressionTree?
let Data: String
// constructor for tree with known left and right
init(Data: String, Left: ExpressionTree? = nil, Right: ExpressionTree? = nil) {
self.Data = Data
self.Left = Left
self.Right = Right
}
// constructor for tree with only data
init(Data:String){
self.Data = Data
self.Left = nil
self.Right = nil
}
// this method returns double regardless of inputs
func ApplyOp(val1: Double, val2: Double, op:String) -> Double?{
switch op {
case "+":
return val1 + val2
case "-":
return val1 - val2
case "*":
return val1 * val2
case "/":
if( val2 != 0 ){
return val1 / val2
}
else{
return nil
}
default:
return nil
}
}
func Solve() -> Double{
return ApplyOp(val1: (Left?.Solve())!, val2: (Right?.Solve())!, op: Data)!
}
ExpressionTreeLeaf Class:
class ExpressionTreeLeaf: ExpressionTree {
init(_ Data: String) {
super.init(Data: "\(Data)")
}
func Solve() -> String {
return Data
}
}
My question is this: While using the debugger, I never seem to go into the ExpressionTreeLeaf constructor. I recursively go into the same solve method, and get error because the parameters are in the wrong place, causing them to be defaulted to 0.0. How to I get the recursive call to go into the ExpressionTreeLeaf class, so that when called, it will return the data of the leaf?
Thank you
EDIT:
here is the method to make the Tree:
expression is in postfix notation
func MakeTree(expression: [String]) -> ExpressionTree{
let precedance: [String: Int] = ["+": 1 , "-": 1, "*": 2, "/": 2]
var stack: Deque<ExpressionTree> = []
for piece in expression {
if(isNumber(check: "\(piece)")){
let tree: ExpressionTreeLeaf = ExpressionTreeLeaf("\(piece)")
stack.append(tree)
}
else if precedance["\(piece)"] != nil{
let tree1: ExpressionTree = stack.removeLast()
let tree2: ExpressionTree = stack.removeLast()
let newTree: ExpressionTree = ExpressionTree(Data: "\(piece)", Left: tree1, Right: tree2)
stack.append(newTree)
}
}
return stack.removeLast()
}
I realize you solved your problem but I would suggest using protocols rather than inheritance. Also, in Swift, value types such as enums and structs are preferred over classes.
First, here are a couple of utils for parsing the expression:
extension String {
var isDigits: Bool {
onlyConsistsOf(charactersIn: .decimalDigits)
}
var isMathOperation: Bool {
onlyConsistsOf(charactersIn: .init(charactersIn: "+-*/"))
}
func onlyConsistsOf(charactersIn set: CharacterSet) -> Bool {
rangeOfCharacter(from: set.inverted) == nil
}
}
extension Character {
var isDigit: Bool {
String(self).isDigits
}
var isMathOperation: Bool {
String(self).isMathOperation
}
}
Now we can get down to the nitty gritty. Let's start with a protocol:
protocol Evaluatable {
func evaluate() -> Double
}
Wether we are dealing with a an operation or an operand we can treat the types the same with protocol conformance. Notice how the Operand and Operation only store properties that they need. In your implementation your ExpressionTreeLeaf inherited from ExpressionTree even though it didn't need the Left or Right properties.
struct Operand: Evaluatable {
let value: Double
func evaluate() -> Double {
value
}
}
struct Operation: Evaluatable {
let lhs: Evaluatable
let rhs: Evaluatable
let op: Character
private var operation: (Double, Double) -> Double {
switch op {
case "+":
return (+)
case "-":
return (-)
case "*":
return (*)
case "/":
return (/)
default:
fatalError("Bad op: \(op)")
}
}
func evaluate() -> Double {
operation(lhs.evaluate(), rhs.evaluate())
}
}
Now let's create a top-level Tree type to store the root component to be evaluated. If you like, you can even make Tree conform to Evaluatable.
struct Tree: Evaluatable {
let root: Evaluatable
func evaluate() -> Double {
root.evaluate()
}
}
This factory method constructs the Tree using the same stack-based algorithm you posted. The stack is declared using the protocol we defined so we can store Operations or Operands.
enum TreeFactory {
static func makeTree(fromExpression expression: String) -> Evaluatable {
var stack: [Evaluatable] = []
for symbol in expression {
if symbol.isDigit {
stack.append(Operand(value: Double(String(symbol)) ?? 0.0))
} else if symbol.isMathOperation {
let rhs = stack.removeLast()
let lhs = stack.removeLast()
stack.append(Operation(lhs: lhs, rhs: rhs, op: symbol))
} else {
stack.removeAll()
break
}
}
return Tree(root: stack.isEmpty ? Operand(value: .zero) : stack.removeLast())
}
}
Let's conform to CustomStringConvertible for debugging purposes:
extension Operand: CustomStringConvertible {
var description: String { "\(value)" }
}
extension Operation: CustomStringConvertible {
var description: String { "(\(lhs) \(op) \(rhs))" }
}
extension Tree: CustomStringConvertible {
var description: String { "Tree: \(root) = \(evaluate())" }
}
Let's try this out:
let expression = "32+32+*3*2+1-2/"
let tree = TreeFactory.makeTree(fromExpression: expression)
print(tree)
Which results in:
Tree: ((((((3.0 + 2.0) * (3.0 + 2.0)) * 3.0) + 2.0) - 1.0) / 2.0) = 38.0
This problem can also be solved using an enum rather than with structs. Here's an alternate solution.
indirect enum TreeNode: Evaluatable {
case operand(Double)
case operation(Character, TreeNode, TreeNode)
case root(TreeNode)
func evaluate() -> Double {
switch self {
case .operand(let value):
return value
case .operation(let op, let lhs, let rhs):
switch op {
case "+":
return lhs.evaluate() + rhs.evaluate()
case "-":
return lhs.evaluate() - rhs.evaluate()
case "*":
return lhs.evaluate() * rhs.evaluate()
case "/":
return lhs.evaluate() / rhs.evaluate()
default:
return .zero
}
case .root(let node):
return node.evaluate()
}
}
}
Let's make another factory method to create an enum-based tree:
extension TreeFactory {
static func makeNodeTree(fromExpression expression: String) -> Evaluatable {
var stack: [TreeNode] = []
for symbol in expression {
if symbol.isDigit {
stack.append(.operand(Double(String(symbol)) ?? 0.0))
} else if symbol.isMathOperation {
let rhs = stack.removeLast()
let lhs = stack.removeLast()
stack.append(.operation(symbol, lhs, rhs))
} else {
stack.removeAll()
break
}
}
return TreeNode.root(stack.isEmpty ? .operand(.zero) : stack.removeLast())
}
}
Let's make our TreeNode debug friendly:
extension TreeNode: CustomStringConvertible {
var description: String {
switch self {
case .operand(let value):
return "\(value)"
case .operation(let op, let lhs, let rhs):
return "(\(lhs) \(op) \(rhs))"
case .root(let node):
return "Tree: \(node) = \(evaluate())"
}
}
}
And now to test it out:
let expression = "32+32+*3*2+1-2/"
let nodeTree = TreeFactory.makeNodeTree(fromExpression: expression)
print(nodeTree)
Here are the results:
Tree: ((((((3.0 + 2.0) * (3.0 + 2.0)) * 3.0) + 2.0) - 1.0) / 2.0) = 38.0
The problem is solved. I originally had incorrect return types which was not allowing me to call functions properly.

Storing Generic Objects in a Heterogeneous Array and retrieving object parameter as the correct type

Ahoy everyone,
I have recently been trying to implement a Node based graph system that passes data between nodes using plugs. Similar to many of the 3D applications like houdini and maya.
I have written a similar system before using Python, and wanted to try this with Swift as my first learning excersise. Boy did I jump into the deep end on this one.
I am stuck now with Swifts Arrays, as I would like to store a list of Generic plugs.
Each plug can have its own value type float, int, color, string, Vector Matrix.
I have read up about Type Erasers and opaque types, but still cant seem to get my values our of a list in a way that I can perform some arithmetic on them.
All and any help that might put me in the direction would be greatly appreciated :D
import Foundation
import MetalKit
protocol genericPlug {
associatedtype T
func GetValue() -> T
}
class Plug<T>:genericPlug{
var _value:T?
var value:T {
get{GetValue()}
set(val){
value = val
}
}
func GetValue() -> T{
return _value!
}
init(_ newValue:T){
_value=newValue
}
}
class Node{
var plugs:[genericPlug] = []
init(){
var p1 = Plug<Int>(0)
var p2 = Plug(vector2(1.2, 3.1))
var p3 = Plug([0.0, 3.1, 0.6, 1])
plugs.append(p1)
plugs.append(p2)
plugs.append(p3)
}
func execute(){
// will access the plugs in the array and perform some sort of calculations on them.
plugs[0].value + 1 // should equal 1
plugs[1].value.x + 0.8 // should have x=2.0 y=3.1
plugs[2].value[1] - 0.1 // should equal 3.0
}
}
Thanks everyone
Use a generic something to extract what you need. Your options are methods and subscripts.
protocol PlugValue {
init()
}
extension Int: PlugValue { }
extension Float: PlugValue { }
extension Double: PlugValue { }
extension SIMD3: PlugValue where Scalar == Int32 { }
struct Plug<Value: PlugValue> {
var value: Value
init(_ value: Value) {
self.value = value
}
}
protocol AnyPlug {
var anyValue: PlugValue { get }
}
extension AnyPlug {
subscript<Value: PlugValue>(type: Value.Type = Value.self) -> Value {
anyValue as? Value ?? .init()
}
func callAsFunction<Value: PlugValue>(_ type: Value.Type = Value.self) -> Value {
anyValue as? Value ?? .init()
}
}
extension Plug: AnyPlug {
var anyValue: PlugValue { value }
}
let plugs: [AnyPlug] = [
Plug(1),
Plug(2.3 as Float),
Plug(4.5),
Plug([6, 7, 8] as SIMD3)
]
plugs[0][Int.self] // 1
plugs[1][Double.self] // 0
plugs[1][] as Float // 2.3
let double: Double = plugs[2]() // 4.5
plugs[3](SIMD3.self).y // 7
With the array of protocols, do you have to down cast them into their Plug when retrieving them every time?
Essentially. This is true of all heterogenous sequences. Here are your options:
extension Array: PlugValue where Element: PlugValue { }
let plug: AnyPlug = Plug([0.1, 1.1, 2.1])
(plug as? Plug<[Double]>)?.value[1]
(plug.anyValue as? [Double])?[1]
extension Plug {
enum Error: Swift.Error {
case typeMismatch
}
}
extension AnyPlug {
func callAsFunction<Value: PlugValue, Return>(_ closure: (Value) -> Return) throws {
guard let value = anyValue as? Value
else { throw Plug<Value>.Error.typeMismatch }
closure(value)
}
}
try plug { (doubles: [Double]) in doubles[1] } // 1.1
try plug { ($0 as [Double])[1] } // 1.1
try plug { $0 as Int } // <Swift.Int>.Error.typeMismatch
I managed to find a solution that worked for my needs.
I am still looking at finding a better way to handle getting the data and their correct type.
import Foundation
import MetalKit
// Creating the PlugType Enum
enum PlugType{
case Integer(Int?)
case Float_(Float?)
case Double_(Double?)
case Vector3(simd_int3)
// default types
static func IntegerType() -> PlugType{ return PlugType.Integer(nil)}
static func FloatType() -> PlugType{ return PlugType.Float_(nil)}
static func DoubleType() -> PlugType{ return PlugType.Double_(nil)}
}
// Implements a way to retrieve the correct value type
extension PlugType{
var IntegerValue: Int{
switch self{
case .Integer(let value):
return value ?? 0
default:
return 0
}
}
var FloatValue: Float{
switch self
{
case .Float_(let value):
return value ?? 0
default:
return 0
}
}
var DoubleValue: Double{
switch self
{
case .Double_(let value):
return value ?? 0
default:
return 0
}
}
}
// Get the string representation of the PlugType
extension PlugType {
var typeName: String{
switch self {
case .Integer: return "Integer"
case .Float_: return "Float"
case .Double_: return "Double"
case .Vector3: return "Vector3"
}
}
var swiftType: Any.Type {
switch self {
case .Integer: return Int.self
case .Float_: return Float.self
case .Double_: return Double.self
case .Vector3: return simd_int3.self
}
}
}
class Plug{
var _value:PlugType?
var type:String? { get{ return _value?.typeName } }
init(_ newValue:PlugType){
_value = newValue
}
func geee<T>(_ input:T) -> T{
switch type {
case "Integer":
return getVal(_value!.IntegerValue) as! T
case "Double":
return getVal(_value!.DoubleValue) as! T
default:
return 0 as! T
}
}
func getVal(_ val:Int) -> Int {
return val
}
func getVal(_ val:Float) -> Float {
return val
}
func getVal(_ val:Double) -> Double {
return val
}
}
var plugs:[Plug] = []
var p1 = Plug(PlugType.Integer(2))

Accessing an Enumeration association value in Swift

In this code I've written a really useless enum that defines a possible Number with Int or Float.
I can't understand how can I access the value that I set with the association. If I try to print it I get just (Enum Value)
enum Number {
case int (Int)
case float (Float)
}
let integer = Number.int(10)
let float = Number.float(10.5)
println("integer is \(integer)")
println("float is \(float)")
For sake of completeness, enum's association value could be accesed also using if statement with pattern matching. Here is solution for original code:
enum Number {
case int (Int)
case float (Float)
}
let integer = Number.int(10)
let float = Number.float(10.5)
if case let .int(i) = integer {
print("integer is \(i)")
}
if case let .float(f) = float {
print("float is \(f)")
}
This solution is described in detail in: https://appventure.me/2015/10/17/advanced-practical-enum-examples/
The value is associated to an instance of the enumeration. Therefore, to access it without a switch, you need to make a getter and make it available explicitly. Something like below:
enum Number {
case int(Int)
case float(Float)
func get() -> NSNumber {
switch self {
case .int(let num):
return num
case .float(let num):
return num
}
}
}
var vInteger = Number.int(10)
var vFloat = Number.float(10.5)
println(vInteger.get())
println(vFloat.get())
Maybe in the future something like that may be automatically created or a shorter convenience could be added to the language.
It surprises me that Swift 2 (as of beta 2) does not address this. Here's an example of a workaround approach for now:
enum TestAssociatedValue {
case One(Int)
case Two(String)
case Three(AnyObject)
func associatedValue() -> Any {
switch self {
case .One(let value):
return value
case .Two(let value):
return value
case .Three(let value):
return value
}
}
}
let one = TestAssociatedValue.One(1)
let oneValue = one.associatedValue() // 1
let two = TestAssociatedValue.Two("two")
let twoValue = two.associatedValue() // two
class ThreeClass {
let someValue = "Hello world!"
}
let three = TestMixed.Three(ThreeClass())
let threeValue = three. associatedValue() as! ThreeClass
print(threeValue.someValue)
If your enum mixes cases with and without associated values, you'll need to make the return type an optional. You could also return literals for some cases (that do not have associated values), mimicking raw-value typed enums. And you could even return the enum value itself for non-associated, non-raw-type cases. For example:
enum TestMixed {
case One(Int)
case Two(String)
case Three(AnyObject)
case Four
case Five
func value() -> Any? {
switch self {
case .One(let value):
return value
case .Two(let value):
return value
case .Three(let value):
return value
case .Four:
return 4
case .Five:
return TestMixed.Five
}
}
}
let one = TestMixed.One(1)
let oneValue = one.value() // 1
let two = TestMixed.Two("two")
let twoValue = two.value() // two
class ThreeClass {
let someValue = "Hello world!"
}
let three = TestMixed.Three(ThreeClass())
let threeValue = three.value() as! ThreeClass
print(threeValue.someValue)
let four = TestMixed.Four
let fourValue = four.value() // 4
let five = TestMixed.Five
let fiveValue = five.value() as! TestMixed
switch fiveValue {
case TestMixed.Five:
print("It is")
default:
print("It's not")
}
// Prints "It is"
like #iQ. answer, you can use property in enum also
enum Number {
case int (Int)
var value: Int {
switch self {
case .int(let value):
return value
}
}
}
let integer = Number.int(10)
println("integer is \(integer.value)")
I have used something like this:
switch number {
case .int(let n):
println("integer is \(n)")
case .float(let n):
println("float is \(n)")
}
If you're using guard, you can write like below:
enum Action {
case .moveTab(index: Int)
}
guard let case .moveTab(index) = someAction else { return }
You can access enum associated value not only through switch! Mirrors come to our aid
Let's create a protocol
protocol MirrorAssociated {
var associatedValues: [String: Any] { get }
}
extension MirrorAssociated {
var associatedValues: [String: Any] {
var values = [String: Any]()
if let associated = Mirror(reflecting: self).children.first {
let children = Mirror(reflecting: associated.value).children
for case let item in children {
if let label = item.label {
values[label] = item.value
}
}
}
return values
}
}
and use it like this:
enum Test: MirrorAssociated {
case test(value: String, anotherValue: Int)
}
Now we can access any associated value without using switch:
let test: Test = .test(value: "Test String", anotherValue: 1337)
if let value = test.associatedValues["value"] as? String {
print("\(value)") // "Test String"
}
if let intValue = test.associatedValues["anotherValue"] as? Int {
print("\(intValue)") // 1337
}
Swift 5
enum Directory {
case accountImages(URL)
case accountData(URL)
var url: URL {
switch self {
case .accountImages(let url):
return url
case .accountData(let url):
return url
}
}
}
func save(to directory: Directory) {
let dir = directory.url
}
Swift 4,
I have created a simple enum with associated values for handling firebase database reference paths
import Firebase
enum FirebaseDBConstants {
case UserLocation(database : DatabaseReference, userID :String)
case UserRequest(database : DatabaseReference, requestID :String)
func getDBPath() -> DatabaseReference {
switch self {
case .UserLocation(let database,let userID):
return database.root.child(FirebaseDBEnvironmentEnum.getCurrentEnvioronMent()).child("Location").child(userID).child("JSON")
case .UserRequest(let database,let requestID):
return database.root.child(FirebaseDBEnvironmentEnum.getCurrentEnvioronMent()).child("Request").child(requestID)
default:
break
}
}
}
Use it like as shown
//Pass Database refenence root as parameter with your request id
let dbPath = FirebaseDBConstants.UserRequest(database: database, requestID: requestId).getDBPath()

How to enumerate an enum with String type?

enum Suit: String {
case spades = "♠"
case hearts = "♥"
case diamonds = "♦"
case clubs = "♣"
}
For example, how can I do something like:
for suit in Suit {
// do something with suit
print(suit.rawValue)
}
Resulting example:
♠
♥
♦
♣
This post is relevant here https://www.swift-studies.com/blog/2014/6/10/enumerating-enums-in-swift
Essentially the proposed solution is
enum ProductCategory : String {
case Washers = "washers", Dryers = "dryers", Toasters = "toasters"
static let allValues = [Washers, Dryers, Toasters]
}
for category in ProductCategory.allValues{
//Do something
}
Swift 4.2+
Starting with Swift 4.2 (with Xcode 10), just add protocol conformance to CaseIterable to benefit from allCases. To add this protocol conformance, you simply need to write somewhere:
extension Suit: CaseIterable {}
If the enum is your own, you may specify the conformance directly in the declaration:
enum Suit: String, CaseIterable { case spades = "♠"; case hearts = "♥"; case diamonds = "♦"; case clubs = "♣" }
Then the following code will print all possible values:
Suit.allCases.forEach {
print($0.rawValue)
}
Compatibility with earlier Swift versions (3.x and 4.x)
If you need to support Swift 3.x or 4.0, you may mimic the Swift 4.2 implementation by adding the following code:
#if !swift(>=4.2)
public protocol CaseIterable {
associatedtype AllCases: Collection where AllCases.Element == Self
static var allCases: AllCases { get }
}
extension CaseIterable where Self: Hashable {
static var allCases: [Self] {
return [Self](AnySequence { () -> AnyIterator<Self> in
var raw = 0
var first: Self?
return AnyIterator {
let current = withUnsafeBytes(of: &raw) { $0.load(as: Self.self) }
if raw == 0 {
first = current
} else if current == first {
return nil
}
raw += 1
return current
}
})
}
}
#endif
I made a utility function iterateEnum() for iterating cases for arbitrary enum types.
Here is the example usage:
enum Suit: String {
case Spades = "♠"
case Hearts = "♥"
case Diamonds = "♦"
case Clubs = "♣"
}
for f in iterateEnum(Suit) {
println(f.rawValue)
}
Which outputs:
♠
♥
♦
♣
But, this is only for debug or test purposes: This relies on several undocumented Swift1.1 compiler behaviors, so, use it at your own risk.
Here is the code:
func iterateEnum<T: Hashable>(_: T.Type) -> GeneratorOf<T> {
var cast: (Int -> T)!
switch sizeof(T) {
case 0: return GeneratorOf(GeneratorOfOne(unsafeBitCast((), T.self)))
case 1: cast = { unsafeBitCast(UInt8(truncatingBitPattern: $0), T.self) }
case 2: cast = { unsafeBitCast(UInt16(truncatingBitPattern: $0), T.self) }
case 4: cast = { unsafeBitCast(UInt32(truncatingBitPattern: $0), T.self) }
case 8: cast = { unsafeBitCast(UInt64($0), T.self) }
default: fatalError("cannot be here")
}
var i = 0
return GeneratorOf {
let next = cast(i)
return next.hashValue == i++ ? next : nil
}
}
The underlying idea is:
Memory representation of enum, excluding enums with associated types, is just an index of cases when the count of the cases is 2...256, it's identical to UInt8, when 257...65536, it's UInt16 and so on. So, it can be unsafeBitcast from corresponding unsigned integer types.
.hashValue of enum values is the same as the index of the case.
.hashValue of enum values bitcasted from invalid index is 0.
Revised for Swift2 and implemented casting ideas from #Kametrixom's answer:
func iterateEnum<T: Hashable>(_: T.Type) -> AnyGenerator<T> {
var i = 0
return anyGenerator {
let next = withUnsafePointer(&i) { UnsafePointer<T>($0).memory }
return next.hashValue == i++ ? next : nil
}
}
Revised for Swift3:
func iterateEnum<T: Hashable>(_: T.Type) -> AnyIterator<T> {
var i = 0
return AnyIterator {
let next = withUnsafePointer(to: &i) {
$0.withMemoryRebound(to: T.self, capacity: 1) { $0.pointee }
}
if next.hashValue != i { return nil }
i += 1
return next
}
}
Revised for Swift3.0.1:
func iterateEnum<T: Hashable>(_: T.Type) -> AnyIterator<T> {
var i = 0
return AnyIterator {
let next = withUnsafeBytes(of: &i) { $0.load(as: T.self) }
if next.hashValue != i { return nil }
i += 1
return next
}
}
The other solutions work but they all make assumptions of for example the number of possible ranks and suits, or what the first and last rank may be. True, the layout of a deck of cards probably isn't going to change much in the foreseeable future. In general, however, it's neater to write code which makes as little assumptions as possible. My solution:
I've added a raw type to the Suit enum, so I can use Suit(rawValue:) to access the Suit cases:
enum Suit: Int {
case Spades = 1
case Hearts, Diamonds, Clubs
func simpleDescription() -> String {
switch self {
case .Spades:
return "spades"
case .Hearts:
return "hearts"
case .Diamonds:
return "diamonds"
case .Clubs:
return "clubs"
}
}
func color() -> String {
switch self {
case .Spades:
return "black"
case .Clubs:
return "black"
case .Diamonds:
return "red"
case .Hearts:
return "red"
}
}
}
enum Rank: Int {
case Ace = 1
case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
case Jack, Queen, King
func simpleDescription() -> String {
switch self {
case .Ace:
return "ace"
case .Jack:
return "jack"
case .Queen:
return "queen"
case .King:
return "king"
default:
return String(self.rawValue)
}
}
}
Below the implementation of Card's createDeck() method. init(rawValue:) is a failable initializer and returns an optional. By unwrapping and checking its value in both while statements, there's no need to assume the number of Rank or Suit cases:
struct Card {
var rank: Rank
var suit: Suit
func simpleDescription() -> String {
return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
}
func createDeck() -> [Card] {
var n = 1
var deck = [Card]()
while let rank = Rank(rawValue: n) {
var m = 1
while let suit = Suit(rawValue: m) {
deck.append(Card(rank: rank, suit: suit))
m += 1
}
n += 1
}
return deck
}
}
Here is how to call the createDeck method:
let card = Card(rank: Rank.Ace, suit: Suit.Clubs)
let deck = card.createDeck()
I stumbled around in the bits and bytes and created an extension that I later found out works very similar to #rintaro's answer. It's used like this:
enum E : EnumCollection {
case A, B, C
}
Array(E.cases()) // [A, B, C]
What's remarkable is that it's usable on any enum without associated values. Note that this doesn't work for enums that have no cases.
As with #rintaro's answer, this code uses the underlying representation of an enum. This representation isn't documented and might change in the future, which would break it. I don't recommend the usage of this in production.
Code (Swift 2.2, Xcode 7.3.1, not working on Xcode 10):
protocol EnumCollection : Hashable {}
extension EnumCollection {
static func cases() -> AnySequence<Self> {
typealias S = Self
return AnySequence { () -> AnyGenerator<S> in
var raw = 0
return AnyGenerator {
let current : Self = withUnsafePointer(&raw) { UnsafePointer($0).memory }
guard current.hashValue == raw else { return nil }
raw += 1
return current
}
}
}
}
Code (Swift 3, Xcode 8.1, not working on Xcode 10):
protocol EnumCollection : Hashable {}
extension EnumCollection {
static func cases() -> AnySequence<Self> {
typealias S = Self
return AnySequence { () -> AnyIterator<S> in
var raw = 0
return AnyIterator {
let current : Self = withUnsafePointer(to: &raw) { $0.withMemoryRebound(to: S.self, capacity: 1) { $0.pointee } }
guard current.hashValue == raw else { return nil }
raw += 1
return current
}
}
}
}
I have no idea why I need typealias, but the compiler complains without it.
You could iterate through an enum by implementing the ForwardIndexType protocol.
The ForwardIndexType protocol requires you to define a successor() function to step through the elements.
enum Rank: Int, ForwardIndexType {
case Ace = 1
case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
case Jack, Queen, King
// ... other functions
// Option 1 - Figure it out by hand
func successor() -> Rank {
switch self {
case .Ace:
return .Two
case .Two:
return .Three
// ... etc.
default:
return .King
}
}
// Option 2 - Define an operator!
func successor() -> Rank {
return self + 1
}
}
// NOTE: The operator is defined OUTSIDE the class
func + (left: Rank, right: Int) -> Rank {
// I'm using to/from raw here, but again, you can use a case statement
// or whatever else you can think of
return left == .King ? .King : Rank(rawValue: left.rawValue + right)!
}
Iterating over an open or closed range (..< or ...) will internally call the successor() function which allows you to write this:
// Under the covers, successor(Rank.King) and successor(Rank.Ace) are called to establish limits
for r in Rank.Ace...Rank.King {
// Do something useful
}
This problem is now much easier. Here is my Swift 4.2 Solution:
enum Suit: Int, CaseIterable {
case None
case Spade, Heart, Diamond, Club
static let allNonNullCases = Suit.allCases[Spade.rawValue...]
}
enum Rank: Int, CaseIterable {
case Joker
case Two, Three, Four, Five, Six, Seven, Eight
case Nine, Ten, Jack, Queen, King, Ace
static let allNonNullCases = Rank.allCases[Two.rawValue...]
}
func makeDeck(withJoker: Bool = false) -> [Card] {
var deck = [Card]()
for suit in Suit.allNonNullCases {
for rank in Rank.allNonNullCases {
deck.append(Card(suit: suit, rank: rank))
}
}
if withJoker {
deck.append(Card(suit: .None, rank: .Joker))
}
return deck
}
Pre 4.2:
I like this solution which I put together after finding "List comprehension in Swift".
It uses Int raws instead of Strings but it avoids typing twice, it allows customizing the ranges, and doesn't hard code raw values.
This is a Swift 4 version of my original solution but see the 4.2 improvement above:
enum Suit: Int {
case None
case Spade, Heart, Diamond, Club
static let allRawValues = Suit.Spade.rawValue...Suit.Club.rawValue
static let allCases = Array(allRawValues.map{ Suit(rawValue: $0)! })
}
enum Rank: Int {
case Joker
case Two, Three, Four, Five, Six
case Seven, Eight, Nine, Ten
case Jack, Queen, King, Ace
static let allRawValues = Rank.Two.rawValue...Rank.Ace.rawValue
static let allCases = Array(allRawValues.map{ Rank(rawValue: $0)! })
}
func makeDeck(withJoker: Bool = false) -> [Card] {
var deck = [Card]()
for suit in Suit.allCases {
for rank in Rank.allCases {
deck.append(Card(suit: suit, rank: rank))
}
}
if withJoker {
deck.append(Card(suit: .None, rank: .Joker))
}
return deck
}
In principle it is possible to do it this way assuming that you don't use raw values assignment for enum's cases:
enum RankEnum: Int {
case Ace
case One
case Two
}
class RankEnumGenerator: Generator {
var i = 0
typealias Element = RankEnum
func next() -> Element? {
let r = RankEnum.fromRaw(i)
i += 1
return r
}
}
extension RankEnum {
static func enumerate() -> SequenceOf<RankEnum> {
return SequenceOf<RankEnum>({ RankEnumGenerator() })
}
}
for r in RankEnum.enumerate() {
println("\(r.toRaw())")
}
If you give the enum a raw Int value it will make looping much easier.
For example, you can use anyGenerator to get a generator that can enumerate across your values:
enum Suit: Int, CustomStringConvertible {
case Spades, Hearts, Diamonds, Clubs
var description: String {
switch self {
case .Spades: return "Spades"
case .Hearts: return "Hearts"
case .Diamonds: return "Diamonds"
case .Clubs: return "Clubs"
}
}
static func enumerate() -> AnyGenerator<Suit> {
var nextIndex = Spades.rawValue
return anyGenerator { Suit(rawValue: nextIndex++) }
}
}
// You can now use it like this:
for suit in Suit.enumerate() {
suit.description
}
// or like this:
let allSuits: [Suit] = Array(Suit.enumerate())
However, this looks like a fairly common pattern, wouldn't it be nice if we could make any enum type enumerable by simply conforming to a protocol? Well with Swift 2.0 and protocol extensions, now we can!
Simply add this to your project:
protocol EnumerableEnum {
init?(rawValue: Int)
static func firstValue() -> Int
}
extension EnumerableEnum {
static func enumerate() -> AnyGenerator<Self> {
var nextIndex = firstRawValue()
return anyGenerator { Self(rawValue: nextIndex++) }
}
static func firstRawValue() -> Int { return 0 }
}
Now any time you create an enum (so long as it has an Int raw value), you can make it enumerable by conforming to the protocol:
enum Rank: Int, EnumerableEnum {
case Ace, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King
}
// ...
for rank in Rank.enumerate() { ... }
If your enum values don't start with 0 (the default), override the firstRawValue method:
enum DeckColor: Int, EnumerableEnum {
case Red = 10, Blue, Black
static func firstRawValue() -> Int { return Red.rawValue }
}
// ...
let colors = Array(DeckColor.enumerate())
The final Suit class, including replacing simpleDescription with the more standard CustomStringConvertible protocol, will look like this:
enum Suit: Int, CustomStringConvertible, EnumerableEnum {
case Spades, Hearts, Diamonds, Clubs
var description: String {
switch self {
case .Spades: return "Spades"
case .Hearts: return "Hearts"
case .Diamonds: return "Diamonds"
case .Clubs: return "Clubs"
}
}
}
// ...
for suit in Suit.enumerate() {
print(suit.description)
}
Swift 3 syntax:
protocol EnumerableEnum {
init?(rawValue: Int)
static func firstRawValue() -> Int
}
extension EnumerableEnum {
static func enumerate() -> AnyIterator<Self> {
var nextIndex = firstRawValue()
let iterator: AnyIterator<Self> = AnyIterator {
defer { nextIndex = nextIndex + 1 }
return Self(rawValue: nextIndex)
}
return iterator
}
static func firstRawValue() -> Int {
return 0
}
}
Updated Code : Swift 4.2/Swift 5
enum Suit: String, CaseIterable {
case spades = "♠"
case hearts = "♥"
case diamonds = "♦"
case clubs = "♣"
}
To access the Output as per question:
for suitKey in Suit.allCases {
print(suitKey.rawValue)
}
Output :
♠
♥
♦
♣
CaseIterable: provides a collection of all of its values.
Types that conform to the CaseIterable protocol are typically enumerations without associated values. When using a CaseIterable type, you can access a collection of all of the type’s cases by using the type’s allCases property.
For accessing cases we are using .allCases. For more information click https://developer.apple.com/documentation/swift/caseiterable
Updated to Swift 2.2+
func iterateEnum<T: Hashable>(_: T.Type) -> AnyGenerator<T> {
var i = 0
return AnyGenerator {
let next = withUnsafePointer(&i) {
UnsafePointer<T>($0).memory
}
if next.hashValue == i {
i += 1
return next
} else {
return nil
}
}
}
It's updated code to Swift 2.2 form #Kametrixom's answer
For Swift 3.0+ (many thanks to #Philip)
func iterateEnum<T: Hashable>(_: T.Type) -> AnyIterator<T> {
var i = 0
return AnyIterator {
let next = withUnsafePointer(&i) {
UnsafePointer<T>($0).pointee
}
if next.hashValue == i {
i += 1
return next
} else {
return nil
}
}
}
Swift 5 Solution:
enum Suit: String, CaseIterable {
case spades = "♠"
case hearts = "♥"
case diamonds = "♦"
case clubs = "♣"
}
// access cases like this:
for suitKey in Suit.allCases {
print(suitKey)
}
Xcode 10 with Swift 4.2
enum Filter: String, CaseIterable {
case salary = "Salary"
case experience = "Experience"
case technology = "Technology"
case unutilized = "Unutilized"
case unutilizedHV = "Unutilized High Value"
static let allValues = Filter.allCases.map { $0.rawValue }
}
Call it
print(Filter.allValues)
Prints:
["Salary", "Experience", "Technology", "Unutilized", "Unutilized High Value"]
Older versions
For enum representing Int
enum Filter: Int {
case salary
case experience
case technology
case unutilized
case unutilizedHV
static let allRawValues = salary.rawValue...unutilizedHV.rawValue // First to last case
static let allValues = allRawValues.map { Filter(rawValue: $0)!.rawValue }
}
Call it like this:
print(Filter.allValues)
Prints:
[0, 1, 2, 3, 4]
For enum representing String
enum Filter: Int {
case salary
case experience
case technology
case unutilized
case unutilizedHV
static let allRawValues = salary.rawValue...unutilizedHV.rawValue // First to last case
static let allValues = allRawValues.map { Filter(rawValue: $0)!.description }
}
extension Filter: CustomStringConvertible {
var description: String {
switch self {
case .salary: return "Salary"
case .experience: return "Experience"
case .technology: return "Technology"
case .unutilized: return "Unutilized"
case .unutilizedHV: return "Unutilized High Value"
}
}
}
Call it
print(Filter.allValues)
Prints:
["Salary", "Experience", "Technology", "Unutilized", "Unutilized High Value"]
I found myself doing .allValues alot throughout my code. I finally figured out a way to simply conform to an Iteratable protocol and have an rawValues() method.
protocol Iteratable {}
extension RawRepresentable where Self: RawRepresentable {
static func iterateEnum<T: Hashable>(_: T.Type) -> AnyIterator<T> {
var i = 0
return AnyIterator {
let next = withUnsafePointer(to: &i) {
$0.withMemoryRebound(to: T.self, capacity: 1) { $0.pointee }
}
if next.hashValue != i { return nil }
i += 1
return next
}
}
}
extension Iteratable where Self: RawRepresentable, Self: Hashable {
static func hashValues() -> AnyIterator<Self> {
return iterateEnum(self)
}
static func rawValues() -> [Self.RawValue] {
return hashValues().map({$0.rawValue})
}
}
// Example
enum Grocery: String, Iteratable {
case Kroger = "kroger"
case HEB = "h.e.b."
case Randalls = "randalls"
}
let groceryHashes = Grocery.hashValues() // AnyIterator<Grocery>
let groceryRawValues = Grocery.rawValues() // ["kroger", "h.e.b.", "randalls"]
EDIT:
Swift Evolution Proposal SE-0194 Derived Collection of Enum Cases proposes a level headed solution to this problem. We see it in Swift 4.2 and newer. The proposal also points out to some workarounds that are similar to some already mentioned here but it might be interesting to see nevertheless.
I will also keep my original post for completeness' sake.
This is yet another approach based on #Peymmankh's answer, adapted to Swift 3.
public protocol EnumCollection: Hashable {}
extension EnumCollection {
public static func allValues() -> [Self] {
typealias S = Self
let retVal = AnySequence { () -> AnyIterator<S> in
var raw = 0
return AnyIterator {
let current = withUnsafePointer(to: &raw) {
$0.withMemoryRebound(to: S.self, capacity: 1) { $0.pointee }
}
guard current.hashValue == raw else { return nil }
raw += 1
return current
}
}
return [S](retVal)
}
enum Rank: Int {
...
static let ranks = (Rank.Ace.rawValue ... Rank.King.rawValue).map{Rank(rawValue: $0)! }
}
enum Suit {
...
static let suits = [Spades, Hearts, Diamonds, Clubs]
}
struct Card {
...
static func fullDesk() -> [Card] {
var desk: [Card] = []
for suit in Suit.suits {
for rank in Rank.ranks {
desk.append(Card(rank: rank,suit: suit))
}
}
return desk
}
}
How about this?
You can try to enumerate like this
enum Planet: String {
case Mercury
case Venus
case Earth
case Mars
static var enumerate: [Planet] {
var a: [Planet] = []
switch Planet.Mercury {
case .Mercury: a.append(.Mercury); fallthrough
case .Venus: a.append(.Venus); fallthrough
case .Earth: a.append(.Earth); fallthrough
case .Mars: a.append(.Mars)
}
return a
}
}
Planet.enumerate // [Mercury, Venus, Earth, Mars]
In Swift 3, when the underlying enum has rawValue, you could implement the Strideable protocol. The advantages are that no arrays of values are created like in some other suggestions and that the standard Swift "for in" loop works, which makes a nice syntax.
// "Int" to get rawValue, and Strideable so we can iterate
enum MyColorEnum: Int, Strideable {
case Red
case Green
case Blue
case Black
// required by Strideable
typealias Stride = Int
func advanced(by n:Stride) -> MyColorEnum {
var next = self.rawValue + n
if next > MyColorEnum.Black.rawValue {
next = MyColorEnum.Black.rawValue
}
return MyColorEnum(rawValue: next)!
}
func distance(to other: MyColorEnum) -> Int {
return other.rawValue - self.rawValue
}
// just for printing
func simpleDescription() -> String {
switch self {
case .Red: return "Red"
case .Green: return "Green"
case .Blue: return "Blue"
case .Black: return "Black"
}
}
}
// this is how you use it:
for i in MyColorEnum.Red ... MyColorEnum.Black {
print("ENUM: \(i)")
}
This solution strikes the right balance of readability and maintainability.
struct Card {
// ...
static func deck() -> Card[] {
var deck = Card[]()
for rank in Rank.Ace.toRaw()...Rank.King.toRaw() {
for suit in [Suit.Spades, .Hearts, .Clubs, .Diamonds] {
let card = Card(rank: Rank.fromRaw(rank)!, suit: suit)
deck.append(card)
}
}
return deck
}
}
let deck = Card.deck()
Sorry, my answer was specific to how I used this post in what I needed to do. For those who stumble upon this question, looking for a way to find a case within an enum, this is the way to do it (new in Swift 2):
Edit: lowercase camelCase is now the standard for Swift 3 enum values
// From apple docs: If the raw-value type is specified as String and you don’t assign values to the cases explicitly, each unassigned case is implicitly assigned a string with the same text as the name of that case.
enum Theme: String
{
case white, blue, green, lavender, grey
}
func loadTheme(theme: String)
{
// this checks the string against the raw value of each enum case (note that the check could result in a nil value, since it's an optional, which is why we introduce the if/let block
if let testTheme = Theme(rawValue: theme)
{
// testTheme is guaranteed to have an enum value at this point
self.someOtherFunction(testTheme)
}
}
For those wondering about the enumerating on an enum, the answers given on this page that include a static var/let containing an array of all enum values are correct. The latest Apple example code for tvOS contains this exact same technique.
That being said, they should build a more convenient mechanism into the language (Apple, are you listening?)!
The experiment was:
EXPERIMENT
Add a method to Card that creates a full deck of cards, with one card of each combination of rank and suit.
So without modifying or enhancing the given code other than adding the method (and without using stuff that hasn't been taught yet), I came up with this solution:
struct Card {
var rank: Rank
var suit: Suit
func simpleDescription() -> String {
return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
}
func createDeck() -> [Card] {
var deck: [Card] = []
for rank in Rank.Ace.rawValue...Rank.King.rawValue {
for suit in Suit.Spades.rawValue...Suit.Clubs.rawValue {
let card = Card(rank: Rank(rawValue: rank)!, suit: Suit(rawValue: suit)!)
//println(card.simpleDescription())
deck += [card]
}
}
return deck
}
}
let threeOfSpades = Card(rank: .Three, suit: .Spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()
let deck = threeOfSpades.createDeck()
Here is a method I use to both iterate an enum and provide multiple values types from one enum
enum IterateEnum: Int {
case Zero
case One
case Two
case Three
case Four
case Five
case Six
case Seven
//tuple allows multiple values to be derived from the enum case, and
//since it is using a switch with no default, if a new case is added,
//a compiler error will be returned if it doesn't have a value tuple set
var value: (french: String, spanish: String, japanese: String) {
switch self {
case .Zero: return (french: "zéro", spanish: "cero", japanese: "nuru")
case .One: return (french: "un", spanish: "uno", japanese: "ichi")
case .Two: return (french: "deux", spanish: "dos", japanese: "ni")
case .Three: return (french: "trois", spanish: "tres", japanese: "san")
case .Four: return (french: "quatre", spanish: "cuatro", japanese: "shi")
case .Five: return (french: "cinq", spanish: "cinco", japanese: "go")
case .Six: return (french: "six", spanish: "seis", japanese: "roku")
case .Seven: return (french: "sept", spanish: "siete", japanese: "shichi")
}
}
//Used to iterate enum or otherwise access enum case by index order.
//Iterate by looping until it returns nil
static func item(index: Int) -> IterateEnum? {
return IterateEnum.init(rawValue: index)
}
static func numberFromSpanish(number: String) -> IterateEnum? {
return findItem { $0.value.spanish == number }
}
//use block to test value property to retrieve the enum case
static func findItem(predicate: ((_: IterateEnum) -> Bool)) -> IterateEnum? {
var enumIndex: Int = -1
var enumCase: IterateEnum?
//Iterate until item returns nil
repeat {
enumIndex += 1
enumCase = IterateEnum.item(index: enumIndex)
if let eCase = enumCase {
if predicate(eCase) {
return eCase
}
}
} while enumCase != nil
return nil
}
}
var enumIndex: Int = -1
var enumCase: IterateEnum?
// Iterate until item returns nil
repeat {
enumIndex += 1
enumCase = IterateEnum.item(index: enumIndex)
if let eCase = enumCase {
print("The number \(eCase) in french: \(eCase.value.french), spanish: \(eCase.value.spanish), japanese: \(eCase.value.japanese)")
}
} while enumCase != nil
print("Total of \(enumIndex) cases")
let number = IterateEnum.numberFromSpanish(number: "siete")
print("siete in japanese: \((number?.value.japanese ?? "Unknown"))")
This is the output:
The number Zero in french: zéro, spanish: cero, japanese: nuru
The number One in french: un, spanish: uno, japanese: ichi
The number Two in french: deux, spanish: dos, japanese: ni
The number Three in french: trois, spanish: tres, japanese: san
The number Four in french: quatre, spanish: cuatro, japanese: shi
The number Five in french: cinq, spanish: cinco, japanese: go
The number Six in french: six, spanish: seis, japanese: roku
The number Seven in french: sept, spanish: siete, japanese: shichi
Total of 8 cases
siete in japanese: shichi
UPDATE
I recently created a protocol to handle the enumeration. The protocol requires an enum with an Int raw value:
protocol EnumIteration {
//Used to iterate enum or otherwise access enum case by index order. Iterate by looping until it returns nil
static func item(index:Int) -> Self?
static func iterate(item:((index:Int, enumCase:Self)->()), completion:(()->())?) {
static func findItem(predicate:((enumCase:Self)->Bool)) -> Self?
static func count() -> Int
}
extension EnumIteration where Self: RawRepresentable, Self.RawValue == Int {
//Used to iterate enum or otherwise access enum case by index order. Iterate by looping until it returns nil
static func item(index:Int) -> Self? {
return Self.init(rawValue: index)
}
static func iterate(item:((index:Int, enumCase:Self)->()), completion:(()->())?) {
var enumIndex:Int = -1
var enumCase:Self?
//Iterate until item returns nil
repeat {
enumIndex += 1
enumCase = Self.item(enumIndex)
if let eCase = enumCase {
item(index: enumIndex, enumCase: eCase)
}
} while enumCase != nil
completion?()
}
static func findItem(predicate:((enumCase:Self)->Bool)) -> Self? {
var enumIndex:Int = -1
var enumCase:Self?
//Iterate until item returns nil
repeat {
enumIndex += 1
enumCase = Self.item(enumIndex)
if let eCase = enumCase {
if predicate(enumCase:eCase) {
return eCase
}
}
} while enumCase != nil
return nil
}
static func count() -> Int {
var enumIndex:Int = -1
var enumCase:Self?
//Iterate until item returns nil
repeat {
enumIndex += 1
enumCase = Self.item(enumIndex)
} while enumCase != nil
//last enumIndex (when enumCase == nil) is equal to the enum count
return enumIndex
}
}
This seems like a hack but if you use raw values you can do something like this
enum Suit: Int {
case Spades = 0, Hearts, Diamonds, Clubs
...
}
var suitIndex = 0
while var suit = Suit.fromRaw(suitIndex++) {
...
}
While dealing with Swift 2.0 here is my suggestion:
I have added the raw type to Suit enum
enum Suit: Int {
then:
struct Card {
var rank: Rank
var suit: Suit
func fullDeck()-> [Card] {
var deck = [Card]()
for i in Rank.Ace.rawValue...Rank.King.rawValue {
for j in Suit.Spades.rawValue...Suit.Clubs.rawValue {
deck.append(Card(rank:Rank(rawValue: i)! , suit: Suit(rawValue: j)!))
}
}
return deck
}
}
As with #Kametrixom answer here I believe returning an array would be better than returning AnySequence, since you can have access to all of Array's goodies such as count, etc.
Here's the re-write:
public protocol EnumCollection : Hashable {}
extension EnumCollection {
public static func allValues() -> [Self] {
typealias S = Self
let retVal = AnySequence { () -> AnyGenerator<S> in
var raw = 0
return AnyGenerator {
let current : Self = withUnsafePointer(&raw) { UnsafePointer($0).memory }
guard current.hashValue == raw else { return nil }
raw += 1
return current
}
}
return [S](retVal)
}
}
Another solution:
enum Suit: String {
case spades = "♠"
case hearts = "♥"
case diamonds = "♦"
case clubs = "♣"
static var count: Int {
return 4
}
init(index: Int) {
switch index {
case 0: self = .spades
case 1: self = .hearts
case 2: self = .diamonds
default: self = .clubs
}
}
}
for i in 0..<Suit.count {
print(Suit(index: i).rawValue)
}
This is a pretty old post, from Swift 2.0. There are now some better solutions here that use newer features of swift 3.0:
Iterating through an Enum in Swift 3.0
And on this question there is a solution that uses a new feature of (the not-yet-released as I write this edit) Swift 4.2:
How do I get the count of a Swift enum?
There are lots of good solutions in this thread and others however some of them are very complicated. I like to simplify as much as possible. Here is a solution which may or may not work for different needs but I think it works well in most cases:
enum Number: String {
case One
case Two
case Three
case Four
case EndIndex
func nextCase () -> Number
{
switch self {
case .One:
return .Two
case .Two:
return .Three
case .Three:
return .Four
case .Four:
return .EndIndex
/*
Add all additional cases above
*/
case .EndIndex:
return .EndIndex
}
}
static var allValues: [String] {
var array: [String] = Array()
var number = Number.One
while number != Number.EndIndex {
array.append(number.rawValue)
number = number.nextCase()
}
return array
}
}
To iterate:
for item in Number.allValues {
print("number is: \(item)")
}
Enums have toRaw() and fromRaw() methods. So if your raw value is an Int, you can iterate from the first to last enum:
enum Suit: Int {
case Spades = 1
case Hearts, Diamonds, Clubs
func simpleDescription() -> String {
switch self {
case .Spades:
return "spades"
case .Hearts:
return "hearts"
case .Diamonds:
return "diamonds"
case .Clubs:
return "clubs"
}
}
}
for i in Suit.Spades.toRaw()...Suit.Clubs.toRaw() {
if let covertedSuit = Suit.fromRaw(i) {
let description = covertedSuit.simpleDescription()
}
}
One gotcha is that you need to test for optional values before running the simpleDescription method, so we set convertedSuit to our value first and then set a constant to convertedSuit.simpleDescription()
Here's my suggested approach. It's not completely satisfactory (I'm very new to Swift and OOP!) but maybe someone can refine it. The idea is to have each enum provide its own range information as .first and .last properties. It adds just two lines of code to each enum: still a bit hard-coded, but at least it's not duplicating the whole set. It does require modifying the Suit enum to be an Int like the Rank enum is, instead of untyped.
Rather than echo the whole solution, here's the code I added to the . enum, somewhere after the case statements (Suit enum is similar):
var first: Int { return Ace.toRaw() }
var last: Int { return King.toRaw() }
and the loop I used to build the deck as an array of String. (The problem definition did not state how the deck was to be structured.)
func createDeck() -> [String] {
var deck: [String] = []
var card: String
for r in Rank.Ace.first...Rank.Ace.last {
for s in Suit.Hearts.first...Suit.Hearts.last {
card = Rank.simpleDescription( Rank.fromRaw(r)!)() + " of " + Suit.simpleDescription( Suit.fromRaw(s)!)()
deck.append( card)
}
}
return deck
}
It's unsatisfactory because the properties are associated to an element rather than to the enum. But it does add clarity to the 'for' loops. I'd like it to say Rank.first instead of Rank.Ace.first. It works (with any element), but it's ugly. Can someone show how to elevate that to the enum level?
And to make it work, I lifted the createDeck method out of the Card struct. I could not figure out how to get a [String] array returned from that struct, and that seems a bad place to put such a method anyway.
I did it using computed property, which returns the array of all values (thanks to this post http://natecook.com/blog/2014/10/loopy-random-enum-ideas/). However, it also uses int raw-values, but I don't need to repeat all members of enumeration in separate property.
UPDATE Xcode 6.1 changed a bit a way how to get enum member using rawValue, so I fixed listing. Also fixed small error with wrong first rawValue.
enum ValidSuits: Int {
case Clubs = 0, Spades, Hearts, Diamonds
func description() -> String {
switch self {
case .Clubs:
return "♣︎"
case .Spades:
return "♠︎"
case .Diamonds:
return "♦︎"
case .Hearts:
return "♥︎"
}
}
static var allSuits: [ValidSuits] {
return Array(
SequenceOf {
() -> GeneratorOf<ValidSuits> in
var i=0
return GeneratorOf<ValidSuits> {
return ValidSuits(rawValue: i++)
}
}
)
}
}