JAL JAL - 7 months ago 165
Swift Question

How Does AnyObject Conform to NSObjectProtocol?

This question was inspired by mz2's answer on the question Check for object type fails with "is not a type" error.

Consider an empty Swift class:

class MyClass { }


Attempting to call any
NSObjectProtocol
methods on an instance of this class will result in a compile-time error:

let obj = MyClass()
obj.isKindOfClass(MyClass.self) // Error: Value of type 'MyClass' has no member 'isKindOfClass'


However, if I cast the instance as
AnyObject
, my object now conforms to
NSObjectProtocol
and I can call the instance methods defined by the protocol:

let obj: AnyObject = MyClass()
obj.isKindOfClass(MyClass.self) // true
obj.conformsToProtocol(NSObjectProtocol) // true
obj.isKindOfClass(NSObject.self) // false


My object doesn't inherit from
NSObject
, but still conforms to
NSObjectProtocol
. How does
AnyObject
conform to
NSObjectProtocol
?

Answer

In the Cocoa / Objective-C world, AnyObject is id. Having cast this object to AnyObject, you can send any known Objective-C message to it, such as isKindOfClass or conformsToProtocol. Now, when you say isKindOfClass or conformsToProtocol, you're not in the Swift world any more; you're talking to Cocoa with Objective-C. So think about how Objective-C sees this object. All classes in the Objective-C world descend from some base class; a baseless class like MyClass is impossible. And every base class in the Objective-C world conforms to the NSObject protocol (which Swift calls NSObjectProtocol); that's what it is to be (or descend from) a base class! Therefore, to get it into the Objective-C world, Swift presents MyClass as descending from a special bridging base class SwiftObject which does indeed conform to NSObjectProtocol (as you can see here: https://github.com/apple/swift/blob/master/stdlib/public/runtime/SwiftObject.mm).