我的应用程序中有内存泄漏的报告,但我无法准确追踪到底发生了什么。我有一个功能,它可以取出旧视图并在新视图中交换。我没有使用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上看到了这一点。
答案 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];
在我的应用程序中,由于过度释放对象而导致延迟崩溃。