首先抱歉我的英语:-)不太好。
我有一个奇怪的内存泄漏与下面的代码(解释后的代码)。 我有一个类,FLWaitingView。这是一个带有等待指示器的简单视图(加上带背景的视图),用于对用户说“等待加载数据”。 它有两个简单的方法:show和dismiss。 在show方法中,我找到主应用程序窗口并添加子视图(等待视图和背景视图,具有不同的动画)。在dismiss方法中,我从superview中删除它。 在每个节目中,我使用静态bool var(is_visible)验证视图是否已经不可见。
奇怪的是:在解雇方法中,我使用:
[self.view removeFromSuperview];
[self.waitingView removeFromSuperview];
从Window中删除两个视图,以避免它们被保留。它们被正确删除,我可以使用NSLog验证这一点(对于每个窗口子视图上的cicle)。但是,在INSTRUMENTS中,使用“标记堆”函数,我看到在每次重新加载(FLWaitingView的新实例,然后显示,然后关闭)时,旧实例保留在内存中并继续增加内存使用量。显然不是调用代码的问题,因为我正确地释放了对象:
//CALLING CODE
//customWaitingView is a property retained
self.customWaitingView = [[[FLWaitingView alloc]init]autorelease];
[self.customWaitingView show];
而且,我认为这是最重要的信息,如果我在另一个方法中移动视图解除,由选择器调用,泄漏就会消失!!!
现在我显示“错误”代码,之后是“修正”。我想了解它为什么会发生。
- (void)show
{
if (!is_visible){
id appDelegate = [[UIApplication sharedApplication] delegate];
UIWindow *window = [appDelegate window];
self.waitingLabel.text = @"Attendere";
self.view.alpha = 1.0;
self.waitingView.alpha = 1.0;
[window addSubview:self.view];
[window addSubview:self.waitingView];
[self.waitingIndicator startAnimating];
self.view.frame = window.frame;
self.waitingView.center = window.center;
// "Pop in" animation for alert
[self doPopInAnimationWithDelegate:self];
// "Fade in" animation for background
[self doFadeInAnimation];
is_visible = YES;
} else {
NSLog(@"FLWaitingView %@ already visible, do nothing", self);
}
}
- (void)dismiss
{
[UIView beginAnimations:nil context:nil];
self.view.alpha = 0.0;
self.waitingView.alpha = 0.0;
[UIView commitAnimations];
[self.waitingIndicator stopAnimating];
//here is the problem
[self.view removeFromSuperview];
[self.waitingView removeFromSuperview];
is_visible = NO;
}
上面的代码是“错误的”,但如果我添加
[self performSelector:@selector(alertDidFadeOut) withObject:nil afterDelay:0.5];
在dismiss方法和一个新方法(显然从dismiss方法中删除冗余代码):
- (void)alertDidFadeOut
{
//here the memory is correctly released
[self.view removeFromSuperview];
[self.waitingView removeFromSuperview];
is_visible = NO;
}
正确释放内存。 为什么?????? 提前谢谢
的Fabio
答案 0 :(得分:0)
你的视图没有像你期望的那样被释放,因为在你发布它的那一刻,仍然有动画链接到它。您只能在动画完成后正确释放它。
你的第二种方法是有效的,因为动画持续时间不到0.5秒 - 在释放所有动画的视图后调用释放代码。
为视图设置动画的正确方法是创建动画并分配其委托,或者更优雅的方法是使用基于块的动画:
- (void)dismiss
{
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
[UIView animateWithDuration: 0.15
animations: ^{
self.view.alpha = 0.0;
self.waitingView.alpha = 0.0;
}
completion: ^(BOOL finished){
[self.waitingIndicator stopAnimating];
[self.view removeFromSuperview];
[self.waitingView removeFromSuperview];
is_visible = NO;
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
}];
}