mway
mway

Reputation: 643

Generic Swift function to test for object type

I'm trying to write a function that takes an object and a type as arguments and returns a boolean indicating whether or not the object is of the given type. There doesn't seem to be a Type type, so I'm not sure how to do this. The best I've been able to do is

func objectIsType<T>(object: AnyObject, someObjectOfType: T) -> Bool {
    return object is T
}

So I can do objectIsType(x, 5), to test if x is an Int or objectIsType(x, "hi") to see if it's a string, but I'd like to be able to call objectIsType(x, Int) to see if x is an Int and objectIsType(x, String) to see if it's a String. Is something like this possible?

Edit:

Airspeed Velocity improved my function and made a great point about it doing exactly what is already does. The new function is this:

func objectIsType<T>(object: Any, someObjectOfType: T.Type) -> Bool {
    return object is T
}

What I'm trying to do is to validate that the values of a [String: Any] dictionary are of the type that I expect. For instance:

let validator: [String: Any.Type] = [
    "gimme an int": Int.self,
    "this better be a string": String.self
]

let validatee: [String: Any] = [
    "gimme an int": 3,
    "this better be a string": "it is!"
]

for (key, type) in validator {
    if !objectIsType(validatee[key], type) {
        selfDestruct()
    }
}

But I'm getting the error, <>protocol.Type is not convertible to T.type. I've looked at the Metatype documentation, but I'm still a bit confused.

Upvotes: 6

Views: 1364

Answers (1)

Airspeed Velocity
Airspeed Velocity

Reputation: 40955

If you want to supply a type as the argument, not a value, you can do the following:

func objectIsType<T>(object: Any, someObjectOfType: T.Type) -> Bool {
    return object is T
}

let a: Any = 1

objectIsType(a, Int.self)  // returns true

NB, AnyObject can only refer to classes, not structs or enums. Int and String are structs. If you change your code, as I have above, to take an Any, it works with structs too.

It might have seemed like your original worked without this change, but really what was happening was the interop was converting your Int into an NSNumber which is a bit of a roundabout way of doing things and won't adapt to the metatype-based approach.

But the question really is, why do you think you need this? is already does exactly this.

Upvotes: 3

Related Questions