如何在没有内存泄漏的ARC中切换UIViews?

时间:2012-08-28 21:33:09

标签: iphone ios ipad uiview

我使用带有ARC的xcode 4.4。我在ViewController.m中动态创建了UIViews:

UIView* myviews[10];

然后在 - (void)viewDidLoad函数中,用我需要的图片填充每个

myviews[viewIndex] = [[UIView alloc]initWithFrame:myrec];
UIImage *testImg;
UIImageView * testImgView = [[UIImageView alloc]init];
testImg = [UIImage imageNamed:[NSString stringWithFormat:@"imgarray%d.png", viewIndex];
[testImgView setImage:testImg];
[myviews[viewIndex] addsubView:testImgView];
viewindex++;

所以一切似乎都很好,当我想从一个视图跳到另一个视图时,接下来我会用两个按钮:

[self.view addSubview:views[viewIndex]];
CATransition *animation = [CATransition animation];
[animation setDelegate:self];
[animation setDuration:1.0f];
[animation setType:@"rippleEffect"];
[animation setSubtype:kCATransitionFromTop];
//[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[self.view.layer addAnimation:animation forKey:@"transitionViewAnimation"];

似乎没什么不好,但是当我在视图之间切换时,内存消耗会以极快的速度增长。然后我会得到内存不足的警告,或者有时应用程序会崩溃。

我曾尝试使用UIViewController数组并在控制器之间切换:没有任何变化,内存低警告是我最终的结果..

也许我需要以某种方式清理记忆?但是怎么样? ARC不允许使用发布等等。

最后我尝试过(对不起,也许不是很专业)之前添加新的子视图是这个

NSArray *viewsToRemove = [self.view subviews];
                    for (UIView *views in viewsToRemove) {
                        [views removeFromSuperview];
                    }

但这也无济于事。

编辑:我需要澄清一件事:我在应用程序执行期间需要每个UIView,这意味着我无法在应用程序退出之前释放它。

EDIT2:编辑代码使其看起来与实际代码更相似。

4 个答案:

答案 0 :(得分:0)

为什么不使用NSMutableArray来存储您的视图?它更容易,我敢说,更安全。

而且,当您从superview中删除它们时,也要从数组中删除它们

作为一般规则,请记住将其存储到数组中会保留它,删除它会释放它,因此如果将其存储到数组中,然后将其添加为子视图,则它将具有保留计数+2。然后你将它从superview中删除(保留计数-1),但它仍然是正数,因为它仍在你的数组中。

答案 1 :(得分:0)

一些想法:

首先,代码中的某些内容不正确,因为您从未创建过testImgView。而不是

testImgView.image = testImg;

你需要

testImgView = [UIImageView viewWithImage:image];

其次,您不需要进入图层动画。 See this code instead...

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition: 110 forView:view cache:NO];  //110 for ripple effect
[UIView commitAnimations];

第三,您可以尝试在viewDidLoad中添加带有标签的所有视图,然后设置可见。

答案 2 :(得分:0)

如果每次发生转换时情况越来越糟,您可以尝试从超级视图中删除时从图层中删除动画。

NSArray *viewsToRemove = [self.view subviews];
                    for (UIView *views in viewsToRemove) {
                        [views removeFromSuperview];
                        [views.layer removeAllAnimations];
                    }

答案 3 :(得分:-1)

当你使用这样的数组结构时(我假设是ivar),当你的包含对象的结构消失时,ARC并不知道它必须释放你的视图。当您清理时,比如在-dealloc方法中,您需要遍历数组并将每个元素设置为nil,然后ARC将知道可以释放该视图。另一个选项是使用Foundation集合类型(例如NSMutableArray)来保存您的观看次数,这样您就不必记得清理它们。

例如:

- (void)dealloc
{
  for( int i = 0; i < 10; i++ )
    myviews[i] = nil;
}

如果在应用程序的生命周期内,您将新视图分配到此数组中,那没关系,ARC会做正确的事情。只要确保你在-dealloc中取消它们。如果您知道以相同的方式完成它们,也可以更早地发布它们,即迭代数组并为每个元素分配nil。