Access the scene from anywhere - iphone

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.

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.

Cocos2d (ARC) not releasing memory of custom CCSprite class

I am using Cocos2d(ARC). i am making a game in which i am using custom CCSprite class
+(id)createMySprite
{
return [[self alloc] initMy] ;
}
This is my CCSprite Class . Where i allocate the memory. I can't write autorelease because of ARC. I have two CCLayer Classes. In first class has just play button with click of that button it replaces the screen and moves second screen. In 2nd Class I fetch to many Custom CCSprite Classes. When i replace to 1st CCLayer class, it never release the memory of 2nd class and memory will continuously increase. Then Crash after reach to 20-30 MB Live memory.
So I, need help regarding this.
Basically, headers are ARC compatible. Source code does not support ARC.
So, you compile Cocos2D as a static lib without enabling ARC and then you link to it in your code in which you can safely use ARC for your classes and custom subclasses of Cocos2D elements.
Please correct me if I am wrong, but there should be no problem with using ARC in your project and have say a CCSprite subclass which uses ARC and does not manually place retain and release messages. Right?
I know this has been around for quite sometime and most likely you have resolved it but for those whom are reading this and are still looking for an answer, here is my understanding of CCNodes and retain cycles.
Basically I have blog'ed about this and I have a design pattern that gets around over retained CCNodes. Here is the link. http://www.rotategears.com/development/ccnode-arc-memory-management/
In a nut shell, if you create a node ivar and don't specify the strength of the reference, it will get a strong reference. Then when you add it as a child to the node that will also maintain the reference, you would have created a double retain which causes problems when the OS tries to release it. The ivar must be week so that you only have a retain count of 1 in this container. Having said that, you then have to be carefull how you assign this weak reference to the ivar as it will need a reference count of 1 before you assign it or else the ivar will be set to nil.

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.

Is my scene going to stay in memory forever

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.