将发布发送到UIViewControllers的NSArray?

时间:2011-07-30 00:31:48

标签: iphone objective-c

如果我有一个UIViewControllers的NSArray并将释放发送到数组,是否会为每个UIViewControllers调用viewDidUnload或dealloc?或两者都没有?

这就是我正在做的事情:

- (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 get released same way ....
}

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

我在每个视图控制器的viewDidUnload和dealloc方法中放置了一个断点,并且它们不会被调用。

3 个答案:

答案 0 :(得分:1)

正如pgb所提到的,你混淆了内存管理和视图控制器生命周期这两个概念。每当卸载视图控制器视图时,都会调用viewDidUnload,这当然只有在加载视图时才会发生。如果没有显示任何视图控制器,您根本不应该看到viewDidUnload被调用。

你应该期待看到dealloc被召唤!

您的问题在于viewControllers数组的初始化:

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

假设viewControllers是使用retain属性的属性,这将泄漏数组,从而泄漏所有数组的内容。问题是你已经分配了一个可变数组(因此保留count = 1),然后你将它分配给viewControllers属性,这将增加保留计数。

在你的dealloc方法中,你(正确地)释放了数组,但这只会将保留计数减少到一个。

我建议的解决方法是将autorelease添加到上面的代码中:

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

进行此更改后,您应该会在视图控制器上看到dealloc被调用。您还应该看到viewDidUnload被调用,因为这些视图控制器的视图被卸载(例如,它们在基于导航控制器的应用程序中从堆栈中弹出)。

答案 1 :(得分:0)

我在这里看到两个问题,每个问题都有一个问题:

如果未加载与viewDidUnload关联的view,则不会调用{p> UIViewController。您基本上混合了两个概念:内存管理(和对象生命周期)与视图控制器生命周期。虽然你可以看到两者之间存在一些并行性,但它们并不一定相关。

您是否在任何时候推动viewController以使其视图可见?如果不是,则肯定不会调用viewDidUnload(不会viewDidLoad)。

对于dealloc,如果在释放对象后没有调用它(并且你认为该对象应该从内存中dealloc),那是因为你有内存泄漏。在您的代码中,我可以很容易地看到初始化代码中的内存泄漏:

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时,

retainCount会在第一行遇到alloc。稍后,当您将其添加到NSMutableArray时,数组会retain,再次突然显示retainCount。要平衡这一点,您需要release两次,但在release方法上只需dealloc一次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]; 。要解决此问题,我会将初始化更改为:

release

将添加您缺少的额外retain并平衡视图控制器上的release {{1}}次调用。

答案 2 :(得分:0)

当您释放数组时,它不会释放它,如果没有其他保留,则允许它被释放。

类似地,如果数组被释放,则释放内部的每个元素,但是对象可能会保留在其他位置,因此不能保证立即解除分配。

一般情况下,UI逻辑在主动呈现时会保留像视图或视图控制器这样的对象,因此直接或通过数组释放它上面的保留不会导致它被解除分配(如果它正在被释放)显示(或者,例如,在导航控制器的堆栈中)。