vendredi 24 juillet 2015

Get rawValue from enum in a generic function

I have some generic reflection code written in swift. In that code I'm having trouble getting the value for properties that are based on an enum. The problem comes down to the fact that I'm not able to execute the .rawValue on the property value which is of type Any. The Swift reflection code will return the enum's value as type Any. So how can I get from an Any to an AnyObject which is the rawValue of the enum.

The only workaround i found so far is extending all enum's with a protocol that has a method that returns a string. Below you can see a unit test that's OK using this workaround.

Is there any way to solve this without adding code to the original enum's?

for my reflection code I need the getRawValue method signature to stay as it is.

class WorkaroundsTests: XCTestCase {
    func testEnumToRaw() {
        let test1 = getRawValue(MyEnumOne.OK)
        XCTAssertTrue(test1 == "OK", "Could nog get the rawvalue using a generic function")
        let test2 = getRawValue(MyEnumTwo.OK)
        XCTAssertTrue(test2 == "1", "Could nog get the rawvalue using a generic function")
    }


    enum MyEnumOne: String, EVRaw {
        case NotOK = "NotOK"
        case OK = "OK"
        func toString() -> String {
            return self.rawValue
        }
    }
    enum MyEnumTwo: Int, EVRaw {
        case NotOK = 0
        case OK = 1
        func toString() -> String {
            return String(self.rawValue)
        }
    }

    func getRawValue(theEnum: Any) -> String {
        // What can we get using reflection:
        let mirror = reflect(theEnum)
        if mirror.disposition == .Aggregate {
            print("Disposition is .Aggregate\n")

            // OK, and now?

            // This does not complile:
            // return enumRawValue(rawValue: theEnum)

            // This works, but I would like to skip this extra protocol
            if let value = theEnum as? EVRaw {
                return value.toString()
            }
        }
        var valueType:Any.Type = mirror.valueType
        print("valueType = \(valueType)\n")
        // No help from these:
        //var value = mirror.value  --> is just theEnum itself
        //var objectIdentifier = mirror.objectIdentifier   --> nil
        //var count = mirror.count   --> 0
        //var summary:String = mirror.summary     --> "(Enum Value)"
        //var quickLookObject = mirror.quickLookObject --> nil

        let toString:String = "\(theEnum)"
        print("\(toString)\n")
        return toString
    }

    func enumRawValue<E: RawRepresentable>(rawValue: E.RawValue) -> String {
        let value = E(rawValue: rawValue)?.rawValue
        return "\(value)"
    }
}

protocol EVRaw {
    func toString() -> String
}





Aucun commentaire:

Enregistrer un commentaire