views:

1388

answers:

4

I need to add more views to a view for handling multiple webaddress and the clicks on the labels. I try to do it in a for statement. My code is something like that:

// we have a UITabbarViewController for holding amongs other the parentViewController
UITabBarController *tabbedViewController = [[UITabBarController alloc] init];

// create the parentViewController
ParentViewController *parentViewController = [[ParentViewController alloc] initWithNibName:@"parentViewController" bundle:nil];
[parentViewController.view setNeedsDisplay];

// add parentViewController into tabbedViewController
tabbedPlayerViewController.viewControllers = [NSArray arrayWithObjects: ... parentViewController, nil];

// All the things are inside a UINavigationController
// push the view
[self.navigationController pushViewController:tabbedViewController animated:YES];

// setting up  the views individually...
// not listed here



for (NSDictionary *url in urls) {

        // init my controller with a nib file 
        UIViewController *webadressViewController = [[WebadressViewController alloc] initWithNibName:@"WebadressViewController" bundle:nil]; 

        // position the view ...
        // ... not listed here

        // add webaddress to parent view
        [parentViewController.view addSubview: webaddressViewController.view];

}

[parentViewController release];
[tabbedViewController release];

I think I may have some memory management problem with that because webaddressViewController has 1 as retain count, so it needs to release somewhere in my code. But if I release it within the for block all the subviews desapears.

My question is how can I release that objects?

(As I see the problem is the following: when I call addSubview on parentViewController it will own the webaddressViewController.view but not the webaddressController itself. Therefore if I release the webaddressViewController its view will desappear too.)

A: 

You should release each view inside the loop immediately after you send the addSubView message. parentViewController.view will retain the views and release them as part of its dealloc.

If you release them before this the view will be deallocated.

You should conversely keep hold of your parentViewController. This is the view controller that owns the view you have created. When you release it, it will release the view you added all the other views to - releasing them in turn.

You release the parentView controller when it is dismissed by the user.

Roger Nolan
Yes, thats what I learned. But if I release the webadressViewController at the last line of the loop, no view will appear.
silicosaur
I think you need to show us more code. how are you displaying the parentView?
Roger Nolan
I added some more code for you.
silicosaur
A: 

Use the autorelease pool which will take care of releasing the object you've allocated when it is no longer needed.

UIViewController *webadressViewController = [[[WebadressViewController alloc] initWithNibName:@"WebadressViewController" bundle:nil] autorelease];

Or, add the release statement on the LAST line of the loop (recommended):

[webaddressViewController release];

If you have a tight loop as it looks like you have here, it will be more efficient if you use the traditional alloc/release pattern.

If you leave the code as is, you have a memory leak.

hyuan
I have tried both, but neighter worked :-( If i release it inside the loop, the views will not appear. This is my problem.
silicosaur
I think you need to post more code. The code you wrote as described has a memory leak. Roger and I are both saying the same thing. Can you post the lines before, in the middle, and after the loop?
hyuan
I added some more code for you.
silicosaur
In your nib, is the file's owner set to the correct object type? tabbedPlayerViewController is that a typo? Do you mean tabbedViewController instead? The only thing that I think is an issue is whether or not parentViewController is prematurely released. If that is, then so will all the subviews.
hyuan
+4  A: 

You are creating a webAdressViewController for each url, but you aren't keeping hold of these view controllers so that you can later release them. If you want to code it like this, you need to also keep an array of webAdressViewControllers as a property in whichever object this code belongs to - and then release them in its dealloc method.

But I wonder why you are creating the webAdressViewControllers in the first place? Do you have any code in the webAdressViewController class, apart from that that creates the view? (If you're talking of releasing the controllers at this point, I suspect not.) If you don't need the controllers later, why not create the views directly at this point, then add them as subviews and release them? That will save you from keeping a load of view controllers around that you don't need.

You also need to keep the tabbed view controller as a property, and release it in dealloc.

The parentViewController has a retain count of two - once for the alloc init, andtwice for being added to the array. If you don't need to access this controller again yourself directly (i.e. if the tabbed controller does all the view cmanagement you need), then you should release it once.

Jane Sales
Dear Jane, thank you for the answer. This is the right solution.
silicosaur
A: 

While probably unrelated to the issue at hand, note that UINavigationController doesn't support pushing a UITabBarController. See this SO question (and answers).

Daniel Dickison