A tricky situation that the language seems to have no support for. (Exceptions, Extensions, Properties)

Try this in an iOS/macOS SpriteKit project:

    let spriteSize = CGSize(width: 32, height: 32)
    let sprite1 = SKSpriteNode(color: .red, size: spriteSize)
    let sprite2 = SKSpriteNode(color: .green, size: spriteSize)
    let physicsBody1 = SKPhysicsBody(rectangleOf: spriteSize)

    sprite1.physicsBody = physicsBody1
    sprite2.physicsBody = physicsBody1

It will crash during runtime: Terminating app due to uncaught exception 'Cant add body, already exists in a world'

I am writing a game engine library/package. Due to its flexible design, there is a chance for the user to end up with a situation where the same SKPhysicsBody may be added to an SKScene more than once, causing a runtime crash, unless the user is extra-careful at every step.

I want to eliminate the possibility of that crash, and have the app simply log a warning then continue running, but the obvious solutions are not very elegant; I will have to subclass many SpriteKit classes and instruct the users of my library to only inherit from those subclasses, which defeats certain goals of the engine.

  • do-try-catch does not help here because No calls to throwing functions occur within 'try' expression

  • I cannot do anything with SKNode.physicsBody via an extension, because you cannot override properties or add observers in extensions.

Any suggestions?

I have no experience with SpriteKit but I guess those are Objective-C exceptions. Those can't be caught in Swift but people have been writing Objective-C wrappers that catch those exceptions and those wrappers are available in Swift then.

Have a look here for example:

1 Like

In your code to add a physics body, can you check if aphysicsbody.node is nil before attempting to add it to a node? Or maybe do this every time:

node.physicsBody = aphysicsbody.copy()

...assuming copy() doesn't copy the .node member?