How to Test Whether Generic Variable Is of Type Anyobject

How to test whether generic variable is of type AnyObject

In Swift 3, everything is bridgeable to AnyObject due to the introduction of _SwiftValue (see this Q&A for more info), that can wrap anything that isn't directly bridgeable to Objective-C in an opaque Objective-C compatible box.

Therefore is AnyObject will always be true, as anything can be represented as an AnyObject via wrapping in a _SwiftValue.

One way to check whether a value is a reference type (as shown in this Q&A) is to type-check the type of the value against the metatype of AnyObject, AnyClass (aka AnyObject.Type).

For generics, if you want to check whether the static type of T is a reference type, you can do:

isObject = T.self is AnyClass

If you want to check whether the dynamic type of a value typed as T is a reference type (such as val in your example), you can use the type(of:) function on the unwrapped value, as the aforementioned Q&A suggests:

if let val = val {
isObject = type(of: val) is AnyClass

// ...
}

The difference between these two approaches is that when T is of type Any (or a non AnyObject abstract type), T.self is AnyClass will return false (which could be useful if you want a box where the value could be a reference or value type) – type(of: val) is AnyClass however, will return whether val itself is a reference type.

Check if `Any` value is object

UPDATE

The code I have shown below is reported as not working in release build.
(Please see Paul Cantrell's comment below.)

Apologies for my "as far as I tested" was too limited.

I'll update this answer when I find some further info about this.


I'm not sure we can see this behaviour in the next beta (or GM or Released version...), but this works as you expect in Xcode 8 beta 6.

let foo: Any = 4
if type(of: foo) is AnyClass {
print("It's an object.")
let object = foo as AnyObject
//do something with `object` that requires reference semantics
} else {
print("It's not an object.") //->It's not an object.
}

class MyClass {}
let bar: Any = MyClass()
if type(of: bar) is AnyClass {
print("It's an object.") //->It's an object.
let object = foo as AnyObject
//do something with `object` that requires reference semantics
} else {
print("It's not an object.")
}

let baz: Any = Array<AnyObject>()
if type(of: baz) is AnyClass {
print("It's an object.")
let object = foo as AnyObject
//do something with `object` that requires reference semantics
} else {
print("It's not an object.") //->It's not an object.
}

I cannot check all possible cases, so there may be some edge cases where this does not work. But as far as I tested, this seems to work as expected.

Swift check type against a generic type

You cannot tell a function what the types of its generic placeholders are (unlike with a generic struct). It must infer them from the context e.g. its arguments.

One way to do what you want is to add another argument related to type T. Rather than pass in a dummy value, you could use the metatype of the type you want:

func generic<T>(parameter: AnyObject, type: T.Type) -> Bool {
if parameter is T {
return true
} else {
return false
}
}

let o: AnyObject = "hello"
generic(o, String.self) // true
generic(o, NSString.self) // also true
generic(o, Int.self) // false

However, I would ask you, what is it you think you're achieving here? You've essentially done nothing more than implement is as a function:

o is String     // true
o is NSString // true
o is Int // false

The point of generics is to operate on arguments generically, but you aren't giving the function any argument of a specific type to actually do any work on (hence the inability to infer one).



Related Topics



Leave a reply



Submit