iOS 内存泄漏导致更改视图控制器崩溃
Posted
技术标签:
【中文标题】iOS 内存泄漏导致更改视图控制器崩溃【英文标题】:iOS memory leaks causing crash in changing view controllers 【发布时间】:2012-03-17 13:55:12 【问题描述】:我创建了两个视图控制器,其中有 UIImage
动画。它经常崩溃并在 xcode 工具中显示内存泄漏。
我的控制器代码-
- (void)viewDidLoad
NSArray *firstArray;
firstArray = [NSArray arrayWithObjects:
[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"up0001" ofType:@"png"]],
[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"up0002" ofType:@"png"]],
::
::
[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"up0035" ofType:@"png"]], nil];
imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
imgView = UIViewContentModeScaleToFill;
[imgView setAnimationImages:firstArray];
imgView.animationDuration = 1.75;
imgView.animationRepeatCount = 0;
[imgView startAnimating];
[self.view addSubview: imgView];
- (void)dealloc
[super dealloc];
[imgView release];
imgView = nil;
我正在通过获取 appdelegate 对象并在我的 Appdelegate.m 中调用以下 appdelegate 函数来将视图控制器更改为我的 rootviewcontroller(请提出任何好的方法)
- (void)changeRootViewController:(NSString *)controllerName
if(self.viewController)
[self.viewController.view removeFromSuperview];
self.viewController=nil;
if (controllerName == @"ViewController")
ViewController *lviewController =[[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
self.viewController = (RootViewController *)lviewController;
[lviewController release];
lviewController.view = nil;
[self.window setRootViewController:self.viewController]; //LEAKS 100%
else if (controllerName == @"MainViewController")
// Use a different VC as roowViewController
MainViewController *lviewController =[[MainViewController alloc] initWithNibName:@"MainViewController" bundle:nil];
self.viewController = (RootViewController *)lviewController;
[lviewController release];
lviewController.view = nil;
[self.window setRootViewController:self.viewController]; //LEAKS 100%
else if (controllerName == @"SecondViewController")
// Use a different VC as roowViewController
SecondViewController *lviewController =[[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:nil];
self.viewController = (RootViewController *)lviewController;
[lviewController release];
lviewController.view = nil;
[self.window setRootViewController:self.viewController]; //LEAKS 100%
[self.window makeKeyAndVisible];
并在我各自的控制器按钮中调用它 -
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate changeRootViewController:@"ViewController"];
或
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate changeRootViewController:@"MainViewController"];
我想从我的主控制器管理视图控制器,在没有导航栏的情况下交换控制器。请帮助我找出最佳方法并避免泄漏。
【问题讨论】:
首先我建议您了解并修复存储泄漏。您是否运行过分析器? 是的,我已经运行了泄漏工具并注释了它向我显示泄漏的代码。像这样 (//Leaks100%) Analyzer 比泄漏工具效果更好,对于第一次通过。它指出你更接近问题。 【参考方案1】:看这段代码:
if (controllerName == @"ViewController")
ViewController *lviewController =[[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
self.viewController = (RootViewController *)lviewController;
[lviewController release];
lviewController.view = nil;
[self.window setRootViewController:self.viewController]; //LEAKS 100%
当你分配“lviewController”时,它的保留计数为1; 当您执行“self.viewController”时,我认为 viewController 是一个保留属性,然后 lviewController 保留计数增加到 2; 然后你释放它,平衡之前的alloc,并且retain count返回1; 最后将它分配给rootViewController,这是一个保留属性,所以lviewController的保留计数再次为2; 最后,当您在窗口中“交换”视图控制器时,lviewController 被释放,因此它的保留计数变为 1。如您所见,它永远不会被释放。这意味着每次调用此函数时都会发生泄漏。
【讨论】:
如果您不需要其他地方的“viewController”属性,只需避免它。因此,在您拥有 alloc-init lviewController 之后,将其添加为 self.window 的根控制器,然后(自动)释放它。一旦窗口将处理这个视图控制器(通过分配不同的根控制器),旧的视图控制器将被释放并释放。最后:为什么不使用 ARC? 感谢您的回答。现在肯定会考虑 ARC。【参考方案2】:您需要更改代码中的一些语句..
这一行没有意义..
imgView = UIViewContentModeScaleToFill;
使用一个函数,您必须将 UIImageView
属性的值设置为 UIViewContentModeScaleToFill
在 UIImageView
文档中找到。
[imageView setContentMode:UIViewContentModeScaleToFill];
这个也一样……
lviewController.view = nil; //Remove this from your code ..
最后更改 dealloc 函数的实现,并记住 [super dealloc];
应该在 dealloc
的任何实现中的最后一个。
- (void)dealloc
[imgView release];
imgView = nil;
[super dealloc];
【讨论】:
【参考方案3】:可能的泄漏是由于“SecondViewController”、“MainViewController”、“ViewController”类中的代码。崩溃的原因是您在 [super dealloc] 之后释放图像视图
试试这个,
- (void)dealloc
[imgView release];
imgView = nil;
[super dealloc];
【讨论】:
以上是关于iOS 内存泄漏导致更改视图控制器崩溃的主要内容,如果未能解决你的问题,请参考以下文章