isRefType check

How do I check that a given existential value is of reference type?
I'm now doing this, is this a good approach?

func isRef(_ v: Any) -> Bool {
    func opened<T>(_: T) -> Bool { false }
    func opened<T: AnyObject>(_: T) -> Bool { true }
    return _openExistential(v, do: opened)
}

Can't you do v is AnyObject?

You'll get false positives because of bridging, e.g. Int to NSNumber, and wrapping to _SwiftValue, I’m afraid

it just doesn't work, e.g.:

struct S {}
S() is AnyObject // true
func isRef(_ v: Any) -> Bool {
    func opened<T>(_: T) -> Bool { false }
    func opened<T: AnyObject>(_: T) -> Bool { true }
    return _openExistential(v, do: opened)
}

func checkMore (_ u: Boo) -> Bool  {
     isRef (u)
}


protocol Boo {}
struct   Bing : Boo {}
class    Bong : Boo {}

let bing : Boo = Bing ()
let bong : Boo = Bong ()

print (isRef (5))
print (isRef (bing))
print (isRef (bong))
print (checkMore (bing))
print (checkMore (bong))

But that gives me:

false
false
false
false
false
func isStaticallyOfAnyObjectType<T>(_: T) -> Bool {
    T.self is AnyObject.Type
}
func isDynamicallyOfAnyObjectType(_ x: Any) -> Bool {
    _openExistential(x, do: isStaticallyOfAnyObjectType)
}

// Usage:
protocol P { }
class C: P { }
isDynamicallyOfAnyObjectType(42) // false
isDynamicallyOfAnyObjectType(42 as Any) // false
isDynamicallyOfAnyObjectType(C()) // true
isDynamicallyOfAnyObjectType(C() as any P) // true

6 Likes

Cool, this seems to work.

Also found this one:

func isRef(_ v: Any) -> Bool {
    Mirror(reflecting: v).displayStyle == .class
}
2 Likes

Classes aren't the only reference types, closures are too, iirc.

So are actors. The only correct answer without false positives requires you to walk over the metatypes, which is what @xwu showcased above.

3 Likes

For the record, both @xwu and Mirror version above give correct result for actors (true) and incorrect result for closures (false).

1 Like

I’ve solved this problem before using type(of: x) is AnyClass. Granted, I don’t think that would work for closures, but in the context where I was using it closures weren’t an expected use-case.

2 Likes

You are right, this simpler version works as good as the other two mentioned above:

func isRef(_ x: Any) -> Bool {
    type(of: x) is AnyClass
}
1 Like