Steve Ives
Steve Ives

Reputation: 8134

Getting a sprite to issue a message when it is removed from the scene after removefromParent?

Is there some way in Swift that I can tell when an SKSpriteNode has actually been removed from the scene? I don't think it's actually done when removeFromParent is called, but instead I think it's done later, when Sprite-Kit thinks it's convenient to do so.

I'm trying to understand the full life cycle and I've noticed that a sprite can still be involved in contact and collisions in didBeginContact even after that sprite has been removed.

If I print out the contents of children (i.e. the array holding all the children of the scene) I see that the sprite is removed as soon as removeFromParent called, but the sprite is still available (at least, for this execution of the SK game loop).

Edit: This question came out from an earlier question of mine concerning didBeginContact being called multiple times for one contact (Sprite-Kit registering multiple collisions for single contact) and discovering that removing the sprite during the first contact did not prevent the subsequent contact(s). (Because SK has 'queued' to contacts in advance.) so I was wondering when the sprite is actually removed.

Upvotes: 5

Views: 123

Answers (3)

Steve Ives
Steve Ives

Reputation: 8134

Am I missing the obvious? So even after removeFromParent the sprite is still around. However, it might well be because I have assigned the node to a temporary SKSpriteNode variable, then as long as that variable is around, there is a strong reference to the node, so it won't be deallocated. Also the SKPhysicsContact object itself will retain a reference to the physicsBody, which has a reference to the node which I think will also prevent allocation.

Update

To see when a sprite is actually released, use the deinit() method:

deinit {
    print("Invader of type \(type) deinitialised")
}

I think this can only be added in a subclass definition, not via an extension.

Having a variable with a strong reference to the node being removed will prevent the node from being de-allocated until that variable is itself removed or changed to refer to something else.

Upvotes: 2

Fluidity
Fluidity

Reputation: 3995

I have a suggestion after reading through the comments... move the node to a place outside of the playable area of your game, then remove it from parent. At this point you don't have to worry about when the physics body gets removed or when SK handles it. Or you could set the physicsBody? to nil at the same time, or use a bitmask flag as KoD suggested.

You can override all of the functions in the SK loop and check to see exactly when your pb is removed: https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/Actions/Actions.html

Upvotes: 1

Alessandro Ornano
Alessandro Ornano

Reputation: 35392

If I've understand your question, I think it's not needed because you can always do:

if let myNode = self.childNode(withName: "//myNode") {
   // ok myNode exist
}

Hope it helps you, you can write this code wherever you think is necessary.

Update:

About the reformulation of your question take a look below to these comments.

Upvotes: 1

Related Questions