追踪可可内存泄漏

时间:2009-11-18 05:13:13

标签: iphone cocoa-touch memory-leaks

我的应用程序中有内存泄漏的报告,但我无法准确追踪到底发生了什么。我有一个功能,它可以取出旧视图并在新视图中交换。我没有使用NavControllers或任何@properties;我正在直接管理我的顶级窗口。

-(void)swapInView:(UIViewController*)newViewController
{
    [currentViewer.view removeFromSuperview];
    printf("Old viewController (%p) has count of %d; now releasing\n",
        currentViewer, [currentViewer retainCount]);
    [currentViewer release];
    currentViewer = 0;

    currentViewer = newViewController;
    [currentViewer retain];

    [mainWindow addSubview:currentViewer.view];
    [mainWindow bringSubviewToFront:currentViewer.view];
}

运行代码时,我显示当前视图控制器正在被释放,然后调用该视图控制器的dealloc方法。但是,仪器/泄漏仍然将其视为泄漏。例如,我打印出来了:

Old viewController (0x119f80) has count of 1; now releasing
Deallocating WelcomeScreenViewController

我可以从地址验证,这是先前分配的相同对象。

我的外部代码如下所示:

MyViewController *theViewController = [[MyViewController alloc]
                                        initWithNibName:nil
                                                 bundle:nil];
[GameMaster swapInNewView:theViewController];
[theViewController release];

是否有人建议如何追踪正在发生的事情?我正在使用3.1.2 SDK,但我也在早期的SDK上看到了这一点。

2 个答案:

答案 0 :(得分:3)

咦。这是一个有趣的。我写了一个快速测试,以确保我们都不是疯了。

最后,这一切都归结为调用代码:

[[MyViewController alloc] initWithNibName:nil bundle:nil];

初始化视图控制器时,其view对象尚未定义,并且在请求之前不会定义。

由于您为nib名称指定了nil,因此必须覆盖loadView子类中的UIViewController才能正确设置视图对象。有关详细信息,请参阅Apple's documentation

loadView的默认实现显然会产生一些幕后魔术,而这种魔法可能会导致内存泄漏。

所以:当你打这个电话时:

[mainWindow addSubview:currentViewer.view];

您实际上正在进行两次调用:

一个:currentViewer.view,这会调用[currentViewer loadView]
二:[mainWindow addSubview:...],它试图添加新加载的视图。

Leaks通过第一次调用识别此行,而不是第二次调用。

要验证,只需修改自定义loadView子类中的UIViewController方法:

- (void)loadView
{
    [self setView:[[UIView new] autorelease]];
}

这可以防止调用默认的loadView,现在不再有泄漏。

显然,一旦你进一步开发这个应用程序,你要么必须在loadView中放置更有意义的东西,要么使用nib。

答案 1 :(得分:0)

请注意removeFromSuperview方法的文档:

“取消接收器与其超视图及其窗口的链接,将其从响应器链中移除,并使其光标矩形无效。接收器也被释放”

我不确定这是不是你的问题,而是在做:

[exampleViewController.view removeFromSuperview];
[exampleViewController release];

在我的应用程序中,由于过度释放对象而导致延迟崩溃。