开发者

Sending release to an NSArray of UIViewControllers?

If I have an NSArray of UIViewControllers and send release to the array, will that call viewDidUnload or dealloc for each of the UIViewControllers? or neither?

Here's what I'm doing:

- (void) viewDidLoad {
   UIViewController* profileController = [[ProfileController alloc] init]; 
   ..........
   //all the other controllers get allocated same way

    self.viewControllers = [[NSMutableArray alloc] initWithObjects: profileController, dietController, exerciseController, progressController, friendsController, nil];

    [profileController release];
    //other controllers g开发者_开发知识库et released same way ....
}

- (void) dealloc {
   [viewControllers release];
   NSLog("DEALLOC!");
   //I know dealloc is being called
   //what happens to the view controllers? 
}

I put a breakpoint in the viewDidUnload and dealloc methods for each of these view controllers, and they don't get called.


As pgb mentioned, you are confusing the two concepts of memory management and view controller life cycle. viewDidUnload will be called whenever the view controllers view is unloaded, which of course will only happen if the view is loaded. In the absence of displaying any of the view controllers you should not expect to see viewDidUnload called at all.

You very much should expect to see dealloc called though!

Your problem is with the initialisation of the viewControllers array:

self.viewControllers = [[NSMutableArray alloc] 
                               initWithObjects: profileController,
                                                dietController,
                                                exerciseController,
                                                progressController,
                                                friendsController,
                                                nil];

Assuming that viewControllers is a property that is using the retain attribute, this will leak the array, and thus all the array's contents. The problem is that you have alloc'd a mutable array (thus retain count = 1), then you are assigning it to the viewControllers property which will increment the retain count.

In your dealloc method you (correctly) release the array, but this will merely decrement the retain count to one.

My suggested fix is to add autorelease to the above code:

self.viewControllers = [[[NSMutableArray alloc] 
                               initWithObjects: profileController,
                                                dietController,
                                                exerciseController,
                                                progressController,
                                                friendsController,
                                                nil] autorelease];

After making this change you should expect to see dealloc being called on the view controllers. You should also expect to see viewDidUnload called as the views of these view controllers are unloaded (for example, as they are popped off of the stack in a navigation-controller based application).


I see two issues here, one for each of the methods not called:

viewDidUnload won't be called if the view associated with the UIViewController wasn't loaded. You are basically mixing two concepts: memory management (and object lifecycle) vs. view controller life cycle. While you can see some parallelism between the two, they are not necessarily related.

Are you, at any point, pushing the viewController so its view is visible? If you are not, then viewDidUnload will certainly not be called (as won't viewDidLoad).

As for dealloc, if it's not called after you release the object (and you think the object should be dealloced from memory) it's because you have a memory leak. In your code, I can easily see the memory leak on the initialization code:

UIViewController* profileController = [[ProfileController alloc] init]; 
..........
//all the other controllers get allocated same way

self.viewControllers = [[NSMutableArray alloc] 
                               initWithObjects: profileController,
                                                dietController,
                                                exerciseController,
                                                progressController,
                                                friendsController,
                                                nil];

profileController gets its retainCount bumped on the first line, when you alloc it. Later, when you add it to a NSMutableArray, the array will retain it, bumping its retainCount once again. To balance that, you would need to release twice, but you are only releaseing once, on your dealloc method. To solve this issue, I would change your initialization to:

UIViewController* profileController = [[[ProfileController alloc] init] autorelease];
..........
//all the other controllers get allocated same way

self.viewControllers = [[NSMutableArray alloc] 
                               initWithObjects: profileController,
                                                dietController,
                                                exerciseController,
                                                progressController,
                                                friendsController,
                                                nil];

which will add the extra release you are missing and balance the retain release calls on your view controllers.


When you release the array, that does not dealloc it, that gives it permission to be dealloced if there are no other retains.

Similarly, if the array is dealloced, each element inside is released, but the objects may be retained elsewhere and hence are not guaranteed to be dealloced immediately.

In general, an object like a view or view controller is retained by the UI logic while it's actively being presented, so releasing your retains on it, either directly or through the array, will not cause it to be dealloced if it's being displayed (or, eg, in the stack of a navigation controller).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜