Distinguishing classes from value types/ObjC bridged types?


(Austin Zheng) #1

Hello,

First, some background. I'm currently working on refactoring the way
mirrors are handled within the Swift standard library (conversion from use
of _Reflectable and _MirrorType to CustomReflectable).

Note that the _MirrorType protocol exposes an 'objectIdentifier' property
which is only relevant for class instances. Each type's mirror would have
to manually implement this property, with mirrors for non-class types
expected to return nil.

CustomReflectable moves away from each type having a custom
_MirrorType-conforming mirror type in favor of using Mirror for everything,
which means that certain manually specified properties such as
'objectIdentifier' and 'summary' disappear, and must be replaced by other
language features.

Now, the current way I distinguish between classes and non-class types (for
the dump() function) is through the following code (variable names are made
up):

if let thisClassThing = thisThing as? AnyObject {
  let theIdentifier = ObjectIdentifier(thisClassThing)
  // do other stuff...
}

(In the context of dump(), this is necessary to ensure that dumping an
object with a cycle of references doesn't result in infinite recursion.)

However, where this breaks down is when Foundation is imported. In this
case, performing as? or is casts/checks on a bridged Swift type such as
String or Array<T> results in the test returning true or the type being
bridged to an NS* object type.

My question is whether or not there exist tools in the stdlib to determine
whether an instance is an instance of a class or not, while also being able
to distinguish between native Swift bridgeable structs and their NS*
equivalents. I have a few ideas I'm exploring but I wanted to run this
question by the community first to see if there's anything I'm missing, or
if anyone has any good ideas.

Thanks for your time, and if you have any questions I'd be happy to clarify.

Best regards,
Austin


(Joe Groff) #2

You can ask if `thisThing.dynamicType is AnyObject.Type`, since the metatypes of bridgeable types don't themselves bridge.

-Joe

···

On Dec 29, 2015, at 4:50 PM, Austin Zheng via swift-dev <swift-dev@swift.org> wrote:

Hello,

First, some background. I'm currently working on refactoring the way mirrors are handled within the Swift standard library (conversion from use of _Reflectable and _MirrorType to CustomReflectable).

Note that the _MirrorType protocol exposes an 'objectIdentifier' property which is only relevant for class instances. Each type's mirror would have to manually implement this property, with mirrors for non-class types expected to return nil.

CustomReflectable moves away from each type having a custom _MirrorType-conforming mirror type in favor of using Mirror for everything, which means that certain manually specified properties such as 'objectIdentifier' and 'summary' disappear, and must be replaced by other language features.

Now, the current way I distinguish between classes and non-class types (for the dump() function) is through the following code (variable names are made up):

if let thisClassThing = thisThing as? AnyObject {
  let theIdentifier = ObjectIdentifier(thisClassThing)
  // do other stuff...
}

(In the context of dump(), this is necessary to ensure that dumping an object with a cycle of references doesn't result in infinite recursion.)

However, where this breaks down is when Foundation is imported. In this case, performing as? or is casts/checks on a bridged Swift type such as String or Array<T> results in the test returning true or the type being bridged to an NS* object type.

My question is whether or not there exist tools in the stdlib to determine whether an instance is an instance of a class or not, while also being able to distinguish between native Swift bridgeable structs and their NS* equivalents. I have a few ideas I'm exploring but I wanted to run this question by the community first to see if there's anything I'm missing, or if anyone has any good ideas.

Thanks for your time, and if you have any questions I'd be happy to clarify.


(Austin Zheng) #3

Perfect! Thanks so much, I'll try that out.

Austin

···

On Dec 29, 2015, at 5:31 PM, Joe Groff <jgroff@apple.com> wrote:

On Dec 29, 2015, at 4:50 PM, Austin Zheng via swift-dev <swift-dev@swift.org> wrote:

Hello,

First, some background. I'm currently working on refactoring the way mirrors are handled within the Swift standard library (conversion from use of _Reflectable and _MirrorType to CustomReflectable).

Note that the _MirrorType protocol exposes an 'objectIdentifier' property which is only relevant for class instances. Each type's mirror would have to manually implement this property, with mirrors for non-class types expected to return nil.

CustomReflectable moves away from each type having a custom _MirrorType-conforming mirror type in favor of using Mirror for everything, which means that certain manually specified properties such as 'objectIdentifier' and 'summary' disappear, and must be replaced by other language features.

Now, the current way I distinguish between classes and non-class types (for the dump() function) is through the following code (variable names are made up):

if let thisClassThing = thisThing as? AnyObject {
let theIdentifier = ObjectIdentifier(thisClassThing)
// do other stuff...
}

(In the context of dump(), this is necessary to ensure that dumping an object with a cycle of references doesn't result in infinite recursion.)

However, where this breaks down is when Foundation is imported. In this case, performing as? or is casts/checks on a bridged Swift type such as String or Array<T> results in the test returning true or the type being bridged to an NS* object type.

My question is whether or not there exist tools in the stdlib to determine whether an instance is an instance of a class or not, while also being able to distinguish between native Swift bridgeable structs and their NS* equivalents. I have a few ideas I'm exploring but I wanted to run this question by the community first to see if there's anything I'm missing, or if anyone has any good ideas.

Thanks for your time, and if you have any questions I'd be happy to clarify.

You can ask if `thisThing.dynamicType is AnyObject.Type`, since the metatypes of bridgeable types don't themselves bridge.

-Joe