奇怪的释放问题

时间:2010-11-14 17:27:31

标签: iphone objective-c memory-management

我有一个奇怪的问题,但我很确定,因为你不是。如果是这样,请帮助我或解释。 我有一个39 UIImages的数组,将用于动画UIImageView。播放动画后,内存不会释放。

- (void)viewDidLoad {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
    NSMutableArray* actionArray = [[NSMutableArray alloc]initWithCapacity:38];

    for (int i=1; i<=39; i++) {
        NSString* path = [[NSBundle mainBundle]pathForResource:[NSString stringWithFormat:@"bg_Level1_%.4d", i] ofType:@"png"];
        UIImage *image = [[UIImage alloc]initWithContentsOfFile:path];
        [path release];
        [actionArray addObject:image];
        [image release];
        NSLog(@"path rc %d image %d", [path retainCount], [image retainCount]); 
    }
    imageView.animationImages = actionArray;
    imageView.animationDuration = 4.0;
    imageView.animationRepeatCount = 1;
    [imageView startAnimating];
    NSLog(@"RetainCount ActArr %d ImageView %d", [actionArray retainCount], [imageView retainCount]);
    [actionArray release];
    [pool drain];
    [imageView release];
    [self performSelector:@selector(playAnimation2) withObject:self afterDelay:5.0];
    [super viewDidLoad];
}

-(void)playAnimation2{
    if ([imageView isAnimating]) {
        [imageView stopAnimating];
    }
    NSLog(@"RetainCount ImageView %d",[imageView retainCount]);
}

没有发现泄漏,但分配的内存量仍为24 MB。

还是没必要?

修改

对不起,我的错。 由于我的代码发生了很多变化,我已经迷失了。分析后我明白了! 非常感谢!

正确的代码是:

- (void)viewDidLoad {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
    NSMutableArray* actionArray = [[NSMutableArray alloc]initWithCapacity:38];

    for (int i=1; i<=39; i++) {
        NSString* path = [[NSBundle mainBundle]pathForResource:[NSString stringWithFormat:@"bg_Level1_%.4d", i] ofType:@"png"];
        UIImage *image = [[UIImage alloc]initWithContentsOfFile:path];
//      [path release];
        [actionArray addObject:image];
        [image release];
        NSLog(@"path rc %d image %d", [path retainCount], [image retainCount]); 
    }
    imageView.animationImages = actionArray;
    imageView.animationDuration = 4.0;
    imageView.animationRepeatCount = 1;
    [imageView startAnimating];
    NSLog(@"RetainCount ActArr %d ImageView %d", [actionArray retainCount], [imageView retainCount]);
    [actionArray release];
    [pool drain];
    [self performSelector:@selector(playAnimation2) withObject:self afterDelay:5.0];
    [super viewDidLoad];
}

-(void)playAnimation2{
    if ([imageView isAnimating]) {
        [imageView stopAnimating];
    }
    [imageView removeFromSuperview];
    imageView.animationImages = nil;
    NSLog(@"RetainCount ImageView %d",[imageView retainCount]);
}

问题在于[path release];

4 个答案:

答案 0 :(得分:6)

这段代码有很多问题。它完全是一个奇迹。

首先:

不要使用-retainCount。

对象的绝对保留计数毫无意义。

您应该调用release与导致保留对象完全相同的次数。不会少(除非你喜欢泄漏),当然,没有更多(除非你喜欢崩溃)。

有关详细信息,请参阅Memory Management Guidelines


现在,一些问题:

  • 您询问是否需要清空数组,然后说 array = nil; ......不起作用。将数组引用设置为nil对数组没有任何作用;不释放或清空它。

  • 您过度释放path

  • 您正在加载一系列图像,将它们粘贴在一个数组中,并且该代码中没有任何内容释放该数组(或清空它)。您的应用程序继续使用内存,并且没有泄漏声音,就像正确的行为一样。

  • 你为什么要发布imageView?该代码中没有任何内容暗示您保留它,即使它是通过其他机制(IB?)保留的,那么释放它也是一个非常奇怪的地方。

答案 1 :(得分:1)

我认为您需要从数组中删除所有对象才能使其正常工作。

尝试从数组中删除对象,然后在完成后再删除数组。

答案 2 :(得分:1)

您正在发布imageView而不将其保留在任何位置,因此您的代码可能还有其他问题。但是,似乎imageView由另一个对象(很可能是超级视图)保留,它将其保留在内存中。这也将使图像数组保留在内存中。

如果您不再需要imageView,请使用[imageView removeFromSuperview];将其从父级中删除

答案 3 :(得分:1)

正如我们已在此处解决的那样:releasing problems

设置imageView.animationImages = nil;

此外,您需要删除[path release];,否则会崩溃。

Memory Management Guide是一个重要的开始。

修改 从不依赖retainCount属性!

编辑2 在该方法中发布imageView显然也是一个错误!