从CGImageRef的UIImage

我正在尝试一个更复杂的项目的简单testing,但我为什么下面的代码崩溃并给出EXC_BAD_ACCESS错误感到困惑?

这是从UIView调用的。

- (void)testing { NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"ball.png" ofType:nil]; CGImageRef imageRef = [[[UIImage alloc]initWithContentsOfFile:imagePath]CGImage]; // CGImageRetain(imageRef); UIImage *newImage = [[UIImage alloc]initWithCGImage:imageRef]; UIImageView *iv = [[UIImageView alloc]initWithImage:newImage]; [self addSubview:iv]; } 

我的猜测是CGImageRef不被保留,但添加CGImageRetain(imageRef); 没有区别。

我也应该注意到这个项目已经开启了ARC。

编辑

我做了一些更多的testing,发现这与ARC直接相关,因为我创build了两个基本项目,只包括上面的代码。 ARC的第一个closures,它完美的工作。 下一个与ARC打开和BAM崩溃与相同的错误。 有趣的是,我第一次在崩溃之前运行项目时,得到了实际的日志错误。

  Error: ImageIO: ImageProviderCopyImageBlockSetCallback 'ImageProviderCopyImageBlockSetCallback' header is not a CFDictionary... 

这条线是问题:

 CGImageRef imageRef = [[[UIImage alloc]initWithContentsOfFile:imagePath]CGImage]; 

创build的UIImage将在这个完整expression式之后立即释放(例如,在这一行之后)。 所以即使试图添加一个CGImageRetain()以后也不行。

根本的问题是从CGImageRef返回的CGImage几乎可以肯定是UIImage一个ivar,并且在UIImage被释放的时候会被释放。

解决这个问题的通用方法是延长UIImage的生命周期。 你可以通过把UIImage放到一个局部variables中,并在你最后一次引用CGImage之后引用它(例如用(void)uiimageVar )来做到这一点。 或者,您可以保留在同一行上的CGImageRef ,如

 CGImageRef imageRef = CGImageRetain([[[UIImage alloc] initWithContentsOfFile:imagePath] CGImage]); 

但是,如果你这样做,不要忘记当你完成后释放imageRef

你写这个:

 CGImageRef imageRef = [[[UIImage alloc]initWithContentsOfFile:imagePath]CGImage]; 

该行创build一个UIImage ,获取它的CGImage属性,然后释放UIImage对象。 由于你不保留CGImageCGImage的唯一所有者就是UIImage 。 所以当UIImage被释放并立即释放时,它也会释放CGImage

UIImage发布之前,您需要保留CGImage 。 尝试这个:

 CGImageRef imageRef = CGImageRetain([[UIImage alloc]initWithContentsOfFile:imagePath].CGImage); 

然后在函数的最后:

 CGImageRelease(imageRef);