I have a relatively cpu and memory intensive program that deals with a lot of images. The way I have my app set up is that when the user presses a button, a "please wait" message will show up and the app delegate will allocate the new view controller and preform the cpu intensive task. When the task is finished, the app delegate will then, using my navigation controller, will push the view with all of my images that were being processed are.
That part works fine, however, when the view controller gets popped, the memory is not released, I think because the app delegate is not releasing the view controller itself, even if the images in the view controller are being released. Therefore, after a couple of times performing this task, as I found out with Instruments, too much memory is allocated, and the app crashes.
I'm not entirely sure how to deallocate the view controller because I need the same pointer to the view controller that performs the task as the one I push. That (I think) rules out allocating the a new view controller in the app delegate right before I want to push it, and I think I need to have a view controller in the instance variable.
Sorry if this is long and confusing. Please Help! Thanks in advance.
The navigation controller is not causing the issue. If you have pushed the view controller and popped it then the retain count will not be affected (I'm not actually sure if the Navigation controller retains a viewcontroller which it pushes). You won't loose the pointer if you release the view controller just the memory which it is pointing too will be released. Sounds like you should just make sure that the dealloc method in your view controller has everything it should have in it (i.e. the large images you are talking about) and then after you pop the view controller just release it manually. The dealloc method in the view controller will then be called automatically for you (providing nothing else has retained it). You should then be able to create a fresh view controller in the next cycle of you program with the same pointer as before.
The navigation controller is not causing the issue. If you have pushed the view controller and popped it then the retain count will not be affected (I'm not actually sure if the Navigation controller retains a viewcontroller which it pushes). You won't loose the pointer if you release the view controller just the memory which it is pointing too will be released. Sounds like you should just make sure that the dealloc method in your view controller has everything it should have in it (i.e. the large images you are talking about) and then after you pop the view controller just release it manually. The dealloc method in the view controller will then be called automatically for you (providing nothing else has retained it). You should then be able to create a fresh view controller in the next cycle of you program with the same pointer as before.
Hope this helps.
M.J.
Ok, so do I have to declare properties for the view controller I am going to push? Also, should I release the view controller in the dealloc of the app delegate or right after I use it?
Ok, so do I have to declare properties for the view controller I am going to push? Also, should I release the view controller in the dealloc of the app delegate or right after I use it?
You don't HAVE to declare a property for the view controller you want to push unless you want some other class to be able to access it's pointer. Although from what I have seen in the apple docs, they always seem to declare properties for pointers to custom classes but I am not sure of the reason for this, maybe someone else can explain.
You should release the view controller in both places as you want to release it after it is popped so that there is no image data hanging around and also it is good practice to release all of the variables you "own" in the dealloc method I think.
I think the above is correct but I would be glad for someone with more experience to correct/improve it.
I tried what you said, and if I release the view controller right after I have pushed it, but if I try to preform the task again, the program throws an exception.
I tried what you said, and if I release the view controller right after I have pushed it, but if I try to preform the task again, the program throws an exception.
I said to try releasing the controller after you POP it off the stack not while it is in use by the navigation controller. See if that works.
I tried what you said, and if I release the view controller right after I have pushed it, but if I try to preform the task again, the program throws an exception.
When you initialize your viewcontroller, set it to autorelease before you push the viewcontroller.
That way, when you push the viewcontroller, it will be added to the viewcontroller stack and autorelease will decrement its retain count.
When you pop the viewcontroller later, its retain count will be decremented to 0, and dealloc will be called, freeing the memory previously allocated to the viewcontroller.
Dollop's method works too, but you need to somehow keep track of the viewcontroller between the push and the pop. Using autorelease is easier.
When you initialize your viewcontroller, set it to autorelease before you push the viewcontroller.
That way, when you push the viewcontroller, it will be added to the viewcontroller stack and autorelease will decrement its retain count.
When you pop the viewcontroller later, its retain count will be decremented to 0, and dealloc will be called, freeing the memory previously allocated to the viewcontroller.
Dollop's method works too, but you need to somehow keep track of the viewcontroller between the push and the pop. Using autorelease is easier.
I must be doing something wrong. What you are saying makes sense, and I tried the autorelease. But, it has the same effect as the other method. As soon as the viewcontroller is popped, the app crashes. I have the view controller declared as an instance in the app delegate, and I call this method to make my pictures. Create is a method inside my mosaic view controller.
Yeah -- the init and the push are too far apart. By the time the push happened, the autorelease pool had already been drained.
Since it looks like you are holding on to your reference to mosaic between the init and the push, you should do [mosaic autorelease] right before pushViewController, instead of in make. That should do the trick.
Yeah -- the init and the push are too far apart. By the time the push happened, the autorelease pool had already been drained.
Since it looks like you are holding on to your reference to mosaic between the init and the push, you should do [mosaic autorelease] right before pushViewController, instead of in make. That should do the trick.
I tried what you said, but to no avail. This is getting really frustrating. I still get EXC_BAD_ACCESS when the view controller is popped.
I tried what you said, but to no avail. This is getting really frustrating. I still get EXC_BAD_ACCESS when the view controller is popped.
Are you sure you are not retaining or releasing mosaic anywhere else in your code? Also, check your dealloc method again to make sure that you are not overreleasing objects. It could be that your dealloc method never worked -- after all, it never got called in the past because your code wasn't releasing the view controller properly.