1

In my program, I currently define an SKSpriteNode as weak at the beginning of my code (in my GameScene class) and declare it like this:

weak var tapFade: SKSpriteNode? = SKSpriteNode(color: UIColor.red, size: CGSize(width: 10, height: 10))

However, since it's weak and has no current references, it is deleted and becomes nil before I require its use. Also in my program, I initialise a weak SKLabelNode like this:

weak var tapToBegin: SKLabelNode? = SKLabelNode(text: "Tap to Begin")

and it isn't deleted immediately unlike the SKSpriteNode. The way I achieved this was by re-declaring the SKLabelNode before I use it like this:

tapToBegin = SKLabelNode(text: "Tap to Begin")

This made the SKLabelNode not nil when I wanted to use it. Although, I tried re-declaring the SKSpriteNode with this same approach, and it still was nil.

Note: This is where the initialisations are and where I need to first use these nodes in my program:

class GameScene: SKScene, SKPhysicsContactDelegate {

    //Initialisations are here
    weak var tapFade: SKSpriteNode? = SKSpriteNode(color: UIColor.red, size: CGSize(width: 10, height: 10))
    weak var tapToBegin: SKLabelNode? = SKLabelNode(text: "Tap to Begin")

    override func didMove(to view: SKView) {
        //I first use these nodes here
    }
}

Is there a way to prevent the SKSpriteNode from immediately being de-initialised? In addition, why is the SKSpriteNode being immediately deleted, and the SKLabelNode not?

J.Treutlein
  • 963
  • 8
  • 23
  • What you stated doesn't make sense. Also I tried your code and both label and a sprite gets deallocated immediately. Because nothing retaining those nodes, they are deallocated as soon as `didMove(toView:)` finishes. In your code there is something that retains that label. – Whirlwind Jan 20 '17 at 09:01
  • Read my comment on @Muffinman2497's answer. – J.Treutlein Jan 20 '17 at 09:55

1 Answers1

2

Using the weak keyword is going to cause the SpriteNode to be picked up by ARC and will be deleted. So when you try to interact with the SpriteNode you will get an exception because it is no longer in memory. Take away the weak before the var keyword.

var tapFade:SKSpriteNode = SKSpriteNode(color: UIColor.red, size: CGSize(width: 10, height: 10))
KissTheCoder
  • 679
  • 6
  • 16
  • But I need the SpriteNode to be weak so it can be deleted later. – J.Treutlein Jan 20 '17 at 04:29
  • Why does it need to be deleted later? Is it causing memory issues? Could you give me more info of what you are trying to do. – KissTheCoder Jan 20 '17 at 04:33
  • Yes it is later in the program. – J.Treutlein Jan 20 '17 at 04:34
  • It's a local variable so it really should have a strong reference. If you're making a level based game you could present a new GameScene for each level which will deinitialize the old scene along with all the sprites created in it. – KissTheCoder Jan 20 '17 at 04:38
  • A strong reference cycle is created though, and that's why I need it weak. – J.Treutlein Jan 20 '17 at 04:39
  • @J.Treutlein How do you know that you have strong reference cycle ? What retaining what? Please be more specific. Is it the scene that isn't deallocated, or something else. – Whirlwind Jan 20 '17 at 09:25
  • Yes the scene isn't being deallocated. The problem I was trying to figure with this post was how to create a weak or unowned variable that isn't deinitialised immediately when defining an SKSpriteNode like I have shown in my post. – J.Treutlein Jan 20 '17 at 09:37
  • When the scene needs to be deallocated, this node is preventing it with strong reference cycle. That is why I need it to be weak or unowned. – J.Treutlein Jan 20 '17 at 09:49
  • @J.Treutlein With the code you have provided, there is no way that scene is being retained. – Whirlwind Jan 20 '17 at 10:42
  • Would an SKSpriteNode with several SKSpriteNode children create a strong reference cycle with the scene? Otherwise, how can I see specifically what code and what objects are being retained? – J.Treutlein Jan 20 '17 at 10:55
  • @J.Treutlein Isn't this helped you already to detect strong reference cycles http://stackoverflow.com/a/41661291/3402095 ? About your first question, I can't really answer it, because it really depends what those nodes are (eg. subclasses of some of SpriteKit classes that inherit from SKNode, or ordinary nodes etc). – Whirlwind 1 hour ago – Whirlwind Jan 20 '17 at 13:38
  • @J.Treutlein Can you not set the variable to Nil when you remove the sprite? – Steve Ives Jan 20 '17 at 14:37
  • @J.Treutlein I think there's a bigger problem. I'm guessing you're creating a home page, or something similar, that requires some degree of permanence to know where to send/load/do next. Without that story/narrative of what you're trying to do, this all seems like odd use of `weak`. Can you tell the larger story of what you're actually trying to do? Some guys like SteveIves and Alessandro are borderline experts on creating a hierarchy of scene menus and their required states/switches. I'm not, but I think I'm recognising the bigger macro problem you might be attempting to deal with. – Confused Jan 20 '17 at 18:41
  • Inside the GameScene class, I have initialised, declared, and used SpriteKit subclasses like SpriteKit nodes , UIColors, SKShapeNodes, CGMutablePaths, etc. XCode says and shows that these are being leaked. Also note I mainly have one SKNode that most of the SKEmitterNodes, and SKSpriteNodes are children of. I have several lists of SKSpriteNodes, and I'm afraid that .removeFromParent() isn't completely removing the nodes from existence. – J.Treutlein Jan 20 '17 at 21:55
  • By profiling with allocations, it seems the major memory issue occurs when I add the SKSpriteNodes to that SKNode that is the parent of most nodes, alongside the other SpriteKit subclasses that are being leaked (the CGMutablePath, SKLabelNodes, SKSpriteNodes, etc. and for some reason XCode says that some of my arrays of CGFloats and Doubles are being leaked to even though arrays are structures). – J.Treutlein Jan 20 '17 at 21:59