3

Let's assume this:

enum MyEnum: String { case value }
let possibleEnum: Any = MyEnum.value
if let str = stringFromPossibleEnum(possibleEnum: possibleEnum)

What's my best bet of implementing stringFromPossibleEnum without knowing enum type name?

func stringFromPossibleEnum(possibleEnum: Any) -> String? {
//    how should this be implemented without knowing enum type name?
}

UPD: ok, it's getting better, with this I can tell if possibleEnum is an enum:

if Mirror(reflecting: possibleEnum).displayStyle == .enum { print("yes!") }

But how to tell if that's a String-based enum?

UPD: this tweet suggests that you can get rawValue as Any from Enum. You can probably then check if that rawValue is String. But how to get rawValue from Mirror?

Dannie P
  • 4,464
  • 3
  • 29
  • 48
  • 5
    I am smelling [`XY`](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) problem here. What are you _exactly_ trying to do? – Ozgur Vatansever Apr 27 '17 at 19:12
  • I'd like to know this side of `swift` better. – Dannie P Apr 27 '17 at 19:20
  • `var a: Any? = str.rawValue` should work just as fine but I am not sure if this is what you want because you are not telling us about what you are really trying to do. – Ozgur Vatansever Apr 27 '17 at 19:22
  • let me rework the question so that it is more clear – Dannie P Apr 27 '17 at 19:22
  • If you just know `a` is just a string-backed enum, and not specifically *what* enum it is, it's not possible (AFAIK) to get the backed value (all you know is it is `RawRepresentable` but you can't declare something as a `RawRepresentable` because of protocol associatedtypes). As @OzgurVatansever said, this sounds like you've already started to go down the wrong path a bit. – Connor Neville Apr 27 '17 at 19:27
  • @ConnorNeville that's exactly what I'm looking for - how to get raw value out of `String`-based `RawRepresentable`. I tried to do this straight way, but obviously it did not work as PATs are somehow different. – Dannie P Apr 27 '17 at 19:34
  • @OzgurVatansever pure interes is the reason. – Dannie P Apr 27 '17 at 19:37
  • `let str = "\(possibleEnum)"` – vacawama Apr 27 '17 at 19:40
  • @vacawama Thank you. This is cool, that's some progress. Now need to figure out how to tell if that `Any` contains enum \ string-based RawRepresentable. – Dannie P Apr 27 '17 at 19:46
  • @DannieP I think this answer contains information you might find useful: http://stackoverflow.com/a/31759324/773625 – mAu Apr 27 '17 at 20:07
  • @mAu thank you. Updating the answer based on that. – Dannie P Apr 27 '17 at 20:27

3 Answers3

5

Ok, so this is basically not doable currently out of the box, as you can't as?-cast to RawRepresentable, and Mirror does not provide rawValue for enums.

I'd say the best bet is to make own protocol, provide default implementation for String-based RawRepresentable and conform all enums manually like so:

Assuming these are the enums:

enum E1: String { case one }
enum E2: String { case two }
enum E3: String { case three }

StringRawRepresentable protocol and default implementation:

protocol StringRawRepresentable {
    var stringRawValue: String { get }
}

extension StringRawRepresentable 
where Self: RawRepresentable, Self.RawValue == String {
    var stringRawValue: String { return rawValue }
}

Conform all needed existing enums to the protocol:

extension E1: StringRawRepresentable {}
extension E2: StringRawRepresentable {}
extension E3: StringRawRepresentable {}

And now we can cast to StringRawRepresentable:

func stringFromPossibleEnum(possibleEnum: Any) -> String? {
    if let e = possibleEnum as? StringRawRepresentable { return e.stringRawValue }
    return nil
}

stringFromPossibleEnum(possibleEnum: E2.two as Any)
Dannie P
  • 4,464
  • 3
  • 29
  • 48
0

Not sure what you're really trying to achieve here, but here it is:

enum MyEnum: String {
    case A
    case B
    case C
}

func stringFromEnum<T: RawRepresentable>(_ value: T) -> String
    where T.RawValue == String {
    return value.rawValue
}

print(stringFromEnum(MyEnum.A))
print(stringFromEnum(MyEnum.B))
print(stringFromEnum(MyEnum.C))
Alexander
  • 59,041
  • 12
  • 98
  • 151
  • 1
    Hi Alex, thanks for your response. If you can get `stringFromEnum` to accept `Any` and return `String` if passed value is a String RawRepresentable - that's what I was interested in – Dannie P Apr 27 '17 at 21:47
0

Based on Danni P's answer

enum E1: String { case one }
enum E2: String { case two }
enum E3: String { case three }


func stringFromPossibleEnum(possibleEnum: Any) -> String? {
    if let e = possibleEnum as? (any RawRepresentable),
       let str = e.rawValue as? String {
        return str
    }
    return nil
}

stringFromPossibleEnum(possibleEnum: E2.two as Any)
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Aug 18 '23 at 03:48