Can't create physics bodies inside initWithCoder

I have a custom SKNode subclass, I want to add a child node with a physics body attached to it. I provide various ways of initializing my custom SKNode so I placed all the code that is shared by all initializers in one function onInit() it looks a bit like this:

func onInit() {
    let physicsBody = SKPhysicsBody(rectangleOfSize: CGSize(width: 100, height: 100))
    physicsBody.affectedByGravity = false

    let child = SKSpriteNode(color: NSColor.grayColor(), size: CGSize(width: 100, height: 100))
    child.position.y = 50
    child.physicsBody = physicsBody
    self.addChild(child)
}

It creates a child node with a physics body attached to it. So I call this function from two initializers: init() and init(coder aDecoder: NSCoder) (after calling super.init of course)

the thing is I noticed when I place a node with my custom class in the GameScene.sks file the physics body isn't created. I know the node is initialized as my custom class because the child sprite node does get created (I can see it), but it just is created without a physics body attached to it.


If I add the node programatically using any other initalizer the child node does have a physics body.


Please note I don't want to add the physics body on my custom node itself (subclass of SKNode), but in a child of that node (though it doesn't work on the custom node either). Here is how I call onInit inside the initializers:

init() {
    ... //Do some initialization
    super.init()
    self.onInit()
}

required init?(coder aDecoder: NSCoder) {
    ...//Some more initialization
    super.init(coder: aDecoder)
    self.onInit()
}


So the question is why is this happening, is it a bug (it looks like on to me), and is there something else I can do?


UPDATE

I later found out the node still has a reference to the physics body I created (calling myNode.physicsBody doesn't return nil), it is just not participating on the physics simulation


Also I found this other question describing a pretty similar issue

Problem with editor and physics body

Is it possible that the child node is being created when a node of your custom subclass is added to the .sks scene in Xcode? The .sks scene is just an archive (that is, a serialized representation) of the object hierarchy that Xcode constructs at design time.


In that case, your parent node might create a fully formed child node (including physics body) on unarchiving from the .sks file, but a later step of the unarchiving might unarchive the child object, replacing the child you created in onInit.


I suggest you use the debugger to set breakpoints in all of the above methods, then trace through the loading to see exactly what happens. What you're looking for is 'init?(coder:)' being called for a child object, which is likely going to mess up your onInit design pattern.

I am not sure I understand, so you are saying that my custom node get unarchived and it creates the full child I am looking for, then the child also gets unarchived and gets replaced by the unarchived version (which would have no physics body). I am not sure why or how would that happen, either way I did check with the debugger and I saw no calls to init?(coder:) on the children.


I am not sure why would that be called, the child node is created programmatically not with the editor (and if it were, they would be two different instances), unless calling init?(coder:) algo unarchives every child after unarchiving itself (if that even makes sense).

The point about archiving is that objects might get unarchived before relationships between them (in particular, parent-child relationships) are re-established. In addition, the parts of Xcode that handle UI design are getting smarter at making custom class behavior available at design time, so Xcode itself might have invoked your initializer when you initially added your parent objects.


On reflection, this doesn't sound especially likely, but I was trying to direct your attention to the actual initialization sequence, to see if you "watch" things go wrong. You have to be especially diligent if you have any reason to suspect that the instance that ends up being the child node is not the same instance you created in onInit.


If it is, then the next step would to try to "watch" the physics body property get set back to nil. If you can see it as non-nil at line 9 of your original code fragment, but see it as nil later, you should be able to set a symbolic breakpoint on the "setPhysicsBody" method to find out when it gets changed.


One other possible issue to consider is that the Sprite Kit documentation describes the "update" cycle that Sprite KIt uses for each frame. You are supposed to make physics changes at a particular point in the cycle. It's possible that setting the physics body at the wrong time could have an unexpected effect:


a. the physics change might be ignored, or


b. the physics change might be deferred until a suitable time in the next update cycle.

Well I did some more debugging and found out that even though the physics body doesn't appear to be participating on the physics simulator (as if it doesn't exist on the physics world) the node still has the reference to that physicsBody (i.e. myNode.physicsBody does not return nil when called from some other scope in my case didMoveToView), so it doesn't get changed at runtime.


It may be that the physics body isn't added to the physics world because of the time I set it, but I think it is unlikely - because I do it essentially inside init (inside onInit, but init(coder:) hasn't returned yet), and there is no problem with any other initializer, so setting the body when initializing is probably OK.

Can't create physics bodies inside initWithCoder
 
 
Q