简体   繁体   中英

Swift array holding any enum String type

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?

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

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)
]

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 ]

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.

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