Checking Protocol Conformance after storing is failing

Consider this enum protocol conformance structure.

enum topA:midA{}
enum topB:midB{}
protocol midA:bottom{}
protocol midB:bottom{}
protocol bottom{}

Store a mix of topA's and topB's in a collection as bottom's.

On retrieval, I need to know if the stored enum is a midA or a midB.

I've tried as

if stored as? midA != nil
if stored as? midA.Type != nil
and
if stored is midA

None of these approaches allow me to differentiate between stored midA's and stored midB's. They all fail.

How can I find out which protocol the stored item conforms to?

Thanks.

Can you show how you store the values in your collection? For example, the following works for me as expected with Swift 5.9:

protocol Bottom {}
protocol MidA: Bottom {}
protocol MidB: Bottom {}
enum TopA: MidA { case a }
enum TopB: MidB { case b }

let values: [any Bottom] = [
  TopA.a,
  TopB.b,
  TopA.a,
  TopB.b,
] 

for value in values {
    if value is MidA {
        print("MidA: \(value)")
    } else if value is MidB {
        print("MidB: \(value)")
    } else {
        print("Unknown: \(value)")
    }
}

// Prints:
// MidA: a
// MidB: b
// MidA: a
// MidB: b
1 Like

To add to what itaiferber said, if you also need the element cast to that type you can do

for value in values {
    if let a = value as? MidA {
        print(type(of: a))
    } else if let b = value as? MidB {
        print(type(of: b))
    } else {
        print("Unknown: \(value)")
    }
}

Edit: oops, the print(type(of:)) isn’t actually proof it’s that cast type but a is actually any MidA and b is any MidB

It’s not the individual enigma that end up being stored, but the types. I apologize for not mentioning this in the original posting. The enigma are being used as namespaces for static public functions.

I need to be able to tell the type of the protocol the final enum type implements.

Thanks.

1 Like

That would be enums not enigmas. Dang spell checker.

1 Like

It's not 100% clear to me what you mean — is it something like this?

let types: [any Bottom.Type] = [
    TopA.self,
    TopB.self,
    TopA.self,
    TopB.self,
]

Because if so, you would replace value is <Protocol> with type is <Protocol>.Type:

for type in types {
    if type is MidA.Type {
        print("\(type) is MidA")
    } else if type is MidB.Type {
        print("\(type) is MidB")
    } else {
        print("Unknown \(type)")
    }
}

// Prints:
// TopA is MidA
// TopB is MidB
// TopA is MidA
// TopB is MidB

If this isn't what you meant, do you mind sharing code showing exactly what you're doing?

I can when I get back to work Monday.

Thanks.

I found a typo in the complicated code not included here. The simplified code works well. My eyeballs just slid over the typo. Sorry to take up your time. Thanks very much.

1 Like