Hi everyone,
I am in serious need of help because I've been bagging my head over this for weeks and I still have a lot of issues with memory leaks and navigations.
The app is based on this navigation scheme:
1. Standard navigation based application with a RootViewController created as a simple view (not a tableView).
2. Pressing a button on the RootView, it performs few operations and then push a tableView on screen.
3. Selecting a row on the table it gets pushed on screen a TabBarController having 4 tabs in it.
Now, I can navigate through the tabs but if I go back to the table and then back again in the TabBarController (selecting any other cell) and navigating again the tabs I get memory leaks which eventually make everything fall apart.
This is what I do to create the elements:
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
// Configure and show the window
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
// Add all of your tabs to the tab bar. You can put as many controllers on as you like, but they will turn into the more button like in the iPod program.
tabBarController.viewControllers = [NSArray arrayWithObjects:tab1Controller, tab2Controller, tab3Controller, nil];
How can I allocate the TabBarController only when I need it and deallocate everything it contains when it disappear?
The leaks appear when I get into a tab from the list, I go other tabs, I go out from a different tab (respect the initial one loaded) and then I get back in.
Any clue?
Also, Is that way to allocate the TabBarController and all the tabs correct?
If I try to alloc all the tabs the same way I alloc the TableViewController (with the temp variable that I dealloc right away) it crashes at launch.
The code in your loadTabBarController method is partly wrong. It needs to be based on the same pattern as in loadTableViewController
value = alloc/init {implicit retain}
self.value = value {implicit retain}
[value release]
and there needs to be another release somewhere, usually in your dealloc method.
View controllers are retained on pushViewController and released on popViewController.
One other style point. If you have view controllers that load from a nib then they should know their own nib name but no other code needs to know what nib a particular view controller loads itself from. I use code like this
I think this is cleaner. The nibname is defined in only one place in the code, which makes it easier to change if needed and reduces the effects of typos.
I haven't worked with a tabbar app so I don't know for certain but the basic idea is probably to have each controller load and unload its nib when it is about to appear and disappear. Use viewWillAppear: and probably viewDidDisappear in the tabbarcontrollers to load and unload the content.
You could have a nib that has just a plain UIView in it that the tabbar controllers load from their init method. Then each has another nib that it loads and unloads dynamically using the API in UINibLoading. Once this second nib is loaded you'd need to addSubview the contents of this second nib to the plain view that was loaded from init. You could removeSubview when the view will go away.
You might also be able to have a viewcontroller that controls the 'real' nib and a simpler controller that is in the viewControllers array for each tab. The same idea as above just that the nib loading would be handled by UIViewController. So you'd load the 'real' view controller in viewWillAppear and release it in viewDidDisappear. You'd then addSubview:realViewController.view same as above.
This shouldn't be too complicated and should keep the memory usage to a minimum.
BTW, I'd also modify the way you're creating the viewcontrollers array. Use
The strategy is to avoid autoreleased objects that will hang around for a long time. For objects with short lifetimes it's ok to make them as autoreleased objects. Having an object that is stored in the autorelease pool for a long time means that it takes up some memory in the autorelease pool and some processing time each time the pool is drained, even though the object isn't going to be released. So don't use the convenience methods for creating objects that will be long-lived, like the view controllers array.
When that is called the specified nib is loaded. Since self is passed as owner, self is the file's owner. When this method returns all the objects in the nib will have been created and any outlets set up in IB will be set on self.
You need to retain the toplevelObjects array and then when you want to dispose of the view in viewDidDisappear you removeSubview and self.toplevelObjects = nil (or otherwise release it)
UIViewController does all this automatically so having a second viewController might be simpler.
a second view controller? that what Im trying to do. I have a table view in a tabbed app. Im trying to make a text area appear above the table so one could type in a new entry for the table. would I use UINibloading for that? How can I implement 2 controllers on the same window?
In the TextViewController do I need to add code to the 'loadView' function?
update:
so initWithNibName doesnt work apparently with tabcontrollers? so I need to use 'loadView' I think. but when I try to create an IBOutlet for the view in the .h file I get an error about declaring a view as a constant?
cheers.rob
Last edited by roberthuttinger; 09-18-2008 at 08:19 AM.
Reason: added code scooby doo