What does NSObject provide, and when should a Swift class inherit from it?
Predict first
What does this print?
class Plain {}
class Cocoa: NSObject {}
let a: Any = Plain()
let b: Any = Cocoa()
print(a is NSObject, b is NSObject)
- true true
- false true
- false false
Mental model. NSObject is the membership card for the Cocoa club. Without it a class works fine in Swift but the club’s machinery will not recognise it.
NSObject is the root of the Cocoa hierarchy. It supplies the runtime interface: isEqual: and hash, description, introspection (isKind(of:), responds(to:), perform), the retain and release machinery, and the hooks behind KVC and KVO. Subclassing it is what makes a class usable by Objective-C and by APIs that expect objects: target-action, KVO, NSCoding, Interface Builder, and many delegate protocols.
A plain Swift class does not inherit from NSObject; its root is an internal Swift base object. Inheriting costs something: a larger object, Objective-C metadata for every @objc member, calls routed through objc_msgSend where they are dynamic, and isEqual semantics you must get right. So do it only when you need the interop. Swift’s is and as? work on both, while isKind(of:) and isMember(of:) are the runtime equivalents.
Only the class that inherits from NSObject is one. A plain Swift class has its own internal root.
Common traps
- Inheriting from
NSObject“just in case”. You pay in size and dispatch for features you do not use. - Overriding
==instead ofisEqual:. Cocoa collections callisEqual:andhash.
They might follow up with
- Which framework features really require it? KVO, target-action selectors,
NSCoding, and anything declared as an Objective-C protocol with class requirements. - Is a Swift
structever anNSObject? No. Value types bridge to Foundation classes when needed, as covered in the bridging section.
Related questions
- 2.9.5 How does equality work for NSObject subclasses, and why do two “equal” objects stay distinct in a Set?
- 4.4.1 What do @objc, @objcMembers, @objc(name), dynamic and @nonobjc each do?
- 2.4.5 How does KVO work in Swift, and why does it sometimes never fire?
What is a class cluster, and what does it change for subclassing and… →