Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift dynamic type checking for structs?

I'm confused about dynamic type checking in Swift.

Specifically, I have a weirdo case where I want to, essentially, write (or find) a function:

func isInstanceOf(obj: Any, type: Any.Type) -> Bool

In Objective-C, this is isKindOfClass, but that won't work because Any.Type includes Swift structs, which are not classes (much less NSObject subclasses).

I can't use Swift is here, because that requires a hardcoded type.

I can't use obj.dynamicType == type because that would ignore subclasses.

The Swift book seems to suggest that this information is lost, and not available for structs at all:

Classes have additional capabilities that structures do not:

...

  • Type casting enables you to check and interpret the type of a class instance at runtime.

(On the Type Casting chapter, it says "Type casting in Swift is implemented with the is and as operators", so it seems to be a broader definition of "type casting" than in other languages.)

However, it can't be true that is/as don't work with structures, since you can put Strings and Ints into an [Any], and pull them out later, and use is String or is Int to figure out what they were. The Type Casting chapter of the Swift Book does exactly this!

Is there something that's as powerful as isKindOfClass but for any Swift instances? This information still must exist at runtime, right?

like image 730
J. Cocoe Avatar asked Sep 19 '16 22:09

J. Cocoe


People also ask

How can I check if an object is of a given type in Swift?

Checking TypeUse the type check operator ( is ) to check whether an instance is of a certain subclass type. The type check operator returns true if the instance is of that subclass type and false if it's not.

What is .type Swift?

A type annotation explicitly specifies the type of a variable or expression. Type annotations begin with a colon ( : ) and end with a type, as the following examples show: let someTuple: (Double, Double) = (3.14159, 2.71828)

Does struct support inheritance Swift?

Structs cannot have inheritance, so have only one type. If you point two variables at the same struct, they have their own independent copy of the data.

How do I know the type of a variable in Swift?

To get type of a variable in Swift, call type(of:) function, and pass the variable as argument for of: parameter.


2 Answers

Actually you can use is operator.

Use the type check operator (is) to check whether an instance is of a certain subclass type. The type check operator returns true if the instance is of that subclass type and false if it is not.

Since struct can't be subclassed, is is guaranteed to be consistent when applied to instance of struct because it will check on it static type, and for classes it will query the dynamic type in runtime.

func `is`<T>(instance: Any, of kind: T.Type) -> Bool{
   return instance is T;
}

This work for both, struct and class.

like image 63
Jans Avatar answered Oct 30 '22 01:10

Jans


As already stated, is/as should work fine with structs. Other corner cases can usually be done with generic functions, something like:

let thing: Any = "hi" as Any

func item<T: Any>(_ item: Any, isType: T.Type) -> Bool {
    return (item as? T) != nil
}

print(item(thing, isType: String.self)) // prints "true"

No idea if this fits your specific use case.

More generally, keep in mind that Swift (currently) requires knowing the type of everything at compile time. If you can't define the specific type that will be passed into a function or set as a variable, neither will the compiler.

like image 25
GetSwifty Avatar answered Oct 30 '22 03:10

GetSwifty