Reputation: 10283
How would I declare an array in Swift which can hold values of any enum
String type?
Here's what I want to do:
enum MyEnumType1: String {
case Foo = "foo"
case Bar = "bar"
}
enum MyEnumType2: String {
case Baz = "baz"
}
// ...
// Compiler error: "Type of expression is ambiguous without more context"
var myArray = [ MyEnumType1.Bar, MyEnumType2.Baz ]
// ^ need to declare type here, but not sure of correct syntax
// pass array over to a protocol which will iterate over the array accessing .rawValues
The two enum types are loosely related but definitely distinct and I need to keep the values separated in this instance, so lumping them all together in one enum and declaring the array of type MyAllIncludingEnumType is not desirable.
Or should I just declare an array of Strings and add the rawValues directly?
I could declare the array as [AnyObject]
but then I'd have to type check each element before attempting to access the .rawValue
, which isn't great either.
Currently I'm only able to use Swift 1.2 on this project, as it's for an app which is already in the App Store and I need to be able to ship updates before Xcode 7 goes GM.
Or is there a cleaner but completely alternate solution to what I want to do?
Upvotes: 3
Views: 3677
Reputation: 22939
An alternative to Kametrixom's answer is to make both enums conform to a common protocol. Both automatically conform to RawRepresentable
, because of the raw value of String
:
protocol RawRepresentable {
typealias RawValue
var rawValue: RawValue { get }
...
}
However, you cannot use this as the type stored in the array since RawRepresentable
is a generic protocol. Instead you could do:
protocol StringRepresentable {
var rawValue: String { get }
}
enum EnumA: String, StringRepresentable {
case A = "A"
}
enum EnumB: String, StringRepresentable {
case B = "B"
}
let array: [StringRepresentable] = [EnumA.A, EnumB.B]
array[0].rawValue // A
Upvotes: 7
Reputation: 14973
Just think about it logically: You want to store multiple enums in an array, so it can be either this or that enum, which is just what an enum is! You can declare an new enum that has associated values of all the accepted other enums like so:
enum A {
case A1, A2
}
enum B {
case B1, B2
}
enum All {
case First(A)
case Second(B)
}
Then you can create an array like this:
let array : [All] = [
.First(.A1),
.Second(.B2),
.Second(.B1),
.First(.A1)
]
Upvotes: 5
Reputation: 958
Try The Below Code
enum MyEnumType1: String {
case Foo = "foo"
case Bar = "bar"
}
enum MyEnumType2: String {
case Baz = "baz"
}
var myArray: [Any] = [ MyEnumType1.Bar, MyEnumType2.Baz ]
Upvotes: 1
Reputation: 2883
If you use the array only to retrieve the rawValues of its elements, then you might simply store the rawValues in the array:
var myArray = [ MyEnumType1.Bar.rawValue, MyEnumType2.Baz.rawValue ]
If instead you want to retrieve the original enum from the array then you will need to type check the elements anyway, so var myArray: [Any] = ...
will not make things worse.
Upvotes: 0