Monday, July 15, 2024

NSCopying in a Swift World

Douglas Hill:

This crash happens because, behind the scenes, the Swift compiler synthesises overrides of a superclass’s designated initialisers. These overridden initialisers crash to prevent objects from being incorrectly initialised from Objective-C.

[…]

From a quick look on Stack Overflow, it seems [self.class alloc] is often a recommended way to create a copy in Objective-C. However, the problem is that the use of self.class dynamically looks up the subclass SocialDocument, but the code here in our framework has no idea that SocialDocument has changed the initialisation requirements.

[…]

If Document were a simpler type where all state that should be copied was public, then subclasses that required copying to create instances of the subclass could override copy(with:) without calling super[…]

[…]

There isn’t a nice way to make copying subclasses work while still adhering to Swift’s principle of reducing the amount of mutable state by using let to create read-only properties.

Adrian Kashivskyy:

PSA: Don’t cast values to NSCopying in Swift or you risk a crash at runtime. Learned this the hard way. 🤠

[…]

Because all values that were originally bridged from Objective-C will pass the alone NSCopying cast, even when they don’t actually conform to the protocol. Such values immediately become instances of _SwiftValue and, like trojans, they will sit there pretending to be innocent but will crash at runtime as soon as they’re accessed.

Previously:

Comments RSS · Twitter · Mastodon

Leave a Comment