Cocos2D Scene Deallocation - iphone

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.

Related

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.

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.

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.

NSOperation + Objective-C Categories = Bad Idea?

I've set up an Objective-C category for an iPhone app's UIImageView class. The category's mission is to help load URL-based images asynchronously with memory/disk caching.
Now, in UIImageView+Cache.m I have access to an NSOperationQueue so I can kick off a loading thread. I create an NSOperation-derived object, initialized with the image URL and the target UIImageView, and a selector to perform on the target once the operation is complete. In the selector method, we set our freshly-loaded image (or, if not found, we set an alternate placeholder image), and we're done!
This works fine, until a UIImageView happens to be removed before the NSOperation completes. For instance, I have a previous/next segmented control in my UI that causes these UIImageViews to be removed and added anew (they're part of a larger "item" that is being viewed in the app), so it's very easy to tap these in rapid succession.
So if you decide to start tapping away before all the images are loaded - KABLAM! Unhappy thread has an invalid object and doesn't know it. :(
The closest thing I can find to help mitigate this is NSOperation's cancel and isCancelled methods, except you can't keep track of which operation object to cancel within a Category, because - if I understand correctly - Categories can't add IVARs to objects!
Maybe that means Categories aren't a good idea here? (Whines: "But I liiiiike Categories! Waaah!")
Advisement appreciated!
I probably wouldn't use a category for this situation. Categories are useful, but are usually unnecessary. I'd only use a category if you have a really good reason to. What exactly are you putting in the category?
I think you could implement the whole thing in the NSOperation subclass, which would be the best solution. Put a retain on the image view so it doesn't get deallocated before the image is downloaded, and cancel the download if the view is not visible anymore. If that's not possible, then subclass UIImageView instead of using a category.
I would say there is no harm in moving this into your own UIImageView subclass. Sure, you may like categories - but if they don't do the job then why hesitate in moving to a design that does?
Are you retaining the UIImageView by the NSOperation? Otherwise the imageView might be freed before the NSOperation completes, leading to kablooi central. You should do a retain and then, once you've done the setImage, do a release.