调用addSubview时可能发生泄漏[iPhone]

时间:2010-12-23 01:28:50

标签: iphone

我正在制作一个在许多XIB之间发生变化的应用。虽然Leaks工具没有调用它,但每当我加载一个新视图时,程序的内存占用量就越来越大。

如果我发表评论:

[self.view addSubview:currentView.view];

程序的内存使用不会改变。

相关代码:

- (void)setPage{
[currentView release]; //retained
switch (pageNumber) {
    case 0:
        currentView = [[TheViewController alloc]
                       initWithNibName:@"PageX"
                       bundle:nil];
        break;
    ///Page 1, Page2, etc.
}
for (clearingView in [self.view subviews]) {
    [clearingView removeFromSuperview];
    //[clearingView release]; = crash
}
[self.view addSubview:currentView.view]; //Leaky
}

我正在使用一个视图控制器。

2 个答案:

答案 0 :(得分:1)

添加子视图时,其保留计数会增加。我没有看到你删除currentView的位置。如果您之前保留了它,然后在此函数中释放它,则不会将其从视图中删除。

尝试添加[currentView removeFromSuperview];作为第一行,看看是否有帮助。

- (void) setPage {
    [currentView.view removeFromSuperview];
    [currentView release];

    switch (pageNumber) {
        case 0:
            currentView = [[TheViewController alloc] initWithNibName:@"PageX" bundle:nil];
            break;
    }
    for (clearingView in [self.view subviews])
        [clearingView removeFromSuperview];

    [self.view addSubview:currentView.view];
}

修改1 : 实际上,我看到你正在删除currentView以及for循环中的所有其他视图。在这种情况下,我真的没有看到你的代码有任何问题。我唯一可以猜到的是,ViewController或View的保留计数会以某种方式升级到其他地方。

  

当发生内存不足警告时,UIViewController类会清除其视图,如果它知道它可以重新加载或稍后再次重新创建它们。如果发生这种情况,它还会调用viewDidUnload方法,让您的代码有机会放弃与视图层次结构相关联的任何对象的所有权,包括使用nib文件加载的对象,viewDidLoad方法中创建的对象以及懒惰创建的对象。运行时并添加到视图层次结构中。通常,如果视图控制器包含出口(属性或包含IBOutlet关键字的原始变量),则应使用viewDidUnload方法放弃这些出口的所有权或您不再需要的任何其他视图相关数据。

答案 1 :(得分:0)

我可以在代码中找到任何明显的信息,但是命名有点令人困惑,你真的需要保留currentView吗?如果你在其他地方使用currentView,那么你可能会添加到会导致泄漏的保留计数。

这就是我倾向于做的事情(注意;我正在快速打字,所以它可能不是100%正确!):

- (void)setPage{

    // Presuming you only want one subview at a time.
    [[[self.view subViews] objectAtIndex:0] removeFromSuperview];

    UIViewController * newController = nil;
    switch (pageNumber) {
    case 0:
        newController = [[TheViewController alloc]
                       initWithNibName:@"PageX"
                       bundle:nil];
        break;
        ///Page 1, Page2, etc.
    }

    [self.view addSubview:newController.view];
    [newController release];
}

我认为你不需要类变量(currentView),这很好地包含在方法中。