Is my scene going to stay in memory forever - iphone

I have a bunch of classes that retain an instance of the scene and I'm starting to think this is going to cause memory management issues for me.
So I have Scene1, Scene2 and a HelperClass that has a property that retains the scene.
When I switch from Scene1 to Scene2 I want everything to be disposed.
I started thinking though am I going to have to manually release the helper class before I call the director to change the scene?
The helper class is retained by a layer that is a child of the scene.
The layer also has a property reference to the scene as a ccnode.
Am I doing this wrong? What is the best way to arrange these things so the memory gets free correctly.
The helper classes do things like creating bullets and adding them to the scene.
I have a similar setup with CCSprites that only exist at the scene level. I keep references to them in the helper classes.

once you add something to a container, a scene or spritesheet or whatever, release it, the container keeps a ref to it, then when you dispose of the container, it will be released.
Scene will not be released if you call push scene, only if you run a new one or call the replaceScene method of CCDirector.

Related

Properly get rid of old SKScene?

I have a few problems in my game and I think I found the source. First of all, I use a CMMotionManager in my game to capture gyro motion, and if the user plays the game twice without closing the app completely first, the gyro can glitch and stop listening to the user, probably because there are two gameScene's, so there are two CMMotionManagers. I also have music playing in the menu that I have to explicitly call stop on when I transition to the gameScene, and it should just be deallocating that scene.
I don't want to deal with multiple view controllers, so my idea is:
Pass the old scene as an argument into the new scene
Once the new scene has loaded, set the old scene to nil
Should this solve my problems?
Calling SKView presentScene: or presentScene:transition: will properly get rid of old SKScene.
However, if there is a strong reference to the old scene, that scene will not be deallocated. My experience of this problem was from Trial and Error.
Please check this code post. It demos when the scene has a weak reference or a strong reference.
https://gist.github.com/naterhat/5399eec40eaa23edbfbc
Without seeing your code, my suggestion to solve the problem is by removing any connection to the scene other than SKView. Log when scene suppose to be deallocated by switching to a new scene. If works, then slowly connect new code. If not deallocated, something is still referencing the old scene.
You can check in Instruments to see if a scene is deallocated. Instead, I find it best to do this by adding logs in the init and dealloc methods of the scene.
- (void)dealloc
{
NSLog(#"%# Scene DEALLOCATED", self.name);
}
- (instancetype)initWithSize:(CGSize)size
{
if(self = [super initWithSize:size]){
self.name = #"TEST";
NSLog(#"%# Scene CREATED", self.name);
}
}
Hope this helps.

How do I keep an object created within a method alive in objective-c?

I want to place multiple pie charts in my application that I create using core plot. I made a wrapper class (lets call it PieChartViewController) that is a view controller and sets up the graph and some buttons and actions to make the graph interactive. To deploy it, I usually just create a property on another view controller that holds the PieChartViewController and when I am initializing this view controller I simply alloc/init thePieChartViewController and add its view to the main view. This usually works fine.
The problem is that on another view, I want to add a variable amount of graphs to the view and this number is decided when the view controller is initialized. I have a method that initializes each PieChartViewController and adds it to an NSMutableDictionary on the parent so that I could keep a reference to them. However, this doesn't seem to keep them alive because I always get BAD_ACCESS 2 crashes and when running instruments I realized that they get deallocated.
So when the PieChartViewControllers are stored on a property it's all good, but when I put them in a dictionary they seem to not be kept alive long enough. I am still not very familiar with memory management in objective-c and I'm not really sure how to go about this, would appreciate any help.
I simply alloc/init the PieChartViewController and add its view to the main view. This usually works fine
It may work fine, but don't do it. This is a misuse of UIViewController. See my answer here: https://stackoverflow.com/a/15962125/341994

Stopping sound in -onExit method of child?

I have three classes, let's call them A,B and C. Class A has a CCLayer class added called B. B has a CCLayer child added too, called C. Now, C plays a sound effect that I would like to stop when scene A is replaced. I assumed that if scene A is replaced by calling -replaceScene, all its children are being removed and cleaned up as well. So I tried to put my piece of code that should stop the sound into the -onExit method of class C. However -onExit is never called on any of the children of the replaced scene. Why is that, and how can I solve this ?
All the methods (stopping the sound etc.) work, I just don't know where to call them. The situation is basically the following: I am in my main scene and if I tap the "main menu" button, I want its children to stop playing any sounds. How do the children know their parent is being released ?
If onExit isn't called for a node it means that it wasn't removed from the scene hierarchy. This points to a memory leak, specifically a retain cycle. You can confirm this by setting a breakpoint in the CCScene's dealloc method. If it doesn't get hit when changing scenes, you're leaking the scene.

Cocos2D Scene Deallocation

When exactly is the dealloc method of a Cocos2D scene called?
Right when another scene is loaded? Or after the scene has finished loading?
Additionally, what must be in the dealloc method if I plan on overwriting it?
Apparently, cocos2D automatically removes all nodes attached to a scene when the scene is deallocated. However, if I plan on overwriting it, specifically what methods must I call?
So how can I manage my scene to make sure they are leak free, 100%?
Thanks in advance!
CCScene's deallocator follows the same rules as any other object's. It will run when the reference count to CCScene reaches zero.
A scene by default doesn't care about another which is about to replace it, but if you're changing scene with a transition, there will be a period of time when two scenes exist at the same time. When the transition ends, the transition will release its reference to the first scene, which will probably be the last such reference, and the first scene will then be deallocated.
In your scene deallocator, put a CCLOG to see exactly when it's run. I put one in each to make sure.
In general, manually release any object which you created using a method starting with alloc, new or copy, whether or not it's a Cocos2D object or otherwise. Other creation methods, such as Cocos2D's node, do not require a manual release, unless you have chosen to retain the object manually yourself as well, which might be advisable if you are not going to add it as a child to another node straight away.
As you have said, adding a node as a child to another does not mean it needs an extra release; Cocos2D will handle that one.
Every object you allocate in your scene class which is not added to the scene as a child must be released explicitly.
A scene is released (and most of the times deallocated if you have not retained it somewhere else) when you replace it (with the replaceScene method)with another scene object or pop it from the scenes stack.
It is always advisable to look in the source code (which contains very helpful comments) and learn what exactly should be done if you customize your scene class.

Access the scene from anywhere

I have a cocos2d hierarchy of layers that is very very deep. I want to access my scene from any of the layers? How would I do this?
If I use a singleton will the retain on the singleton prevent the layer from being garbage collected when scenes are changed using the director?
i guess one approch is to use [CCDirector sharedDirector].runningScene sould do the trick if you want to get access to the current running scene, but about decleraing your scene as a singleton yes it prevents garbage collector if you retain your scene whenever iit's created but you have to remeber to release it whenever you are done with your scene.