3

In Swift 2, it was possible to test whether a value is an object by using is AnyObject.

In Swift 3, however, all value types are automatically boxed in a _SwiftValue object when typecast to AnyObject. This means that the expression x is AnyObject is always true in Swift 3. The compiler will even warn about this:

'is' test is always true

Swift 3’s autoboxing of values comes with a memory allocation cost. Is there a runtime test to determine whether a given value is an object in Swift 3?

Paul Cantrell
  • 9,175
  • 2
  • 40
  • 48
  • Indeed, this question is a duplicate of http://stackoverflow.com/questions/39184911/check-if-any-value-is-object. Funny that I couldn’t manage to turn that one up when I was searching for the answer! This version has more detail about _why_ this changed in Swift 3, but the essential question & answer are the same as that other one. – Paul Cantrell Sep 29 '16 at 01:02

1 Answers1

1

This works:

func isObject(_ val: Any) -> Bool {
    return type(of: val) is AnyObject.Type
}

For example:

class Foo { }
isObject(7))    // false
isObject(Foo()) // true

In some quick performance tests, this function is at least 1000x faster than the memory allocation cost of as AnyObject. So it’s worth doing this test if special-casing value types can save you from having to wrap values as objects.

Paul Cantrell
  • 9,175
  • 2
  • 40
  • 48
  • Note that, as of Swift 3.0, this breaks in optimized release builds when taking the type of an existential: https://bugs.swift.org/browse/SR-2867 – Paul Cantrell Oct 07 '16 at 22:33