来自CGImageRef的UIImage

Eck*_*dia 5 uiimage ios ios5

我正在尝试一个更复杂的项目的简单测试,但我感到困惑的是为什么下面的代码崩溃并给出一个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];
 }
Run Code Online (Sandbox Code Playgroud)

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

我还应该注意到这个项目已经启用了ARC.

编辑

我做了一些测试,并发现这与ARC直接相关,因为我创建了2个基本项目,仅包括上面的代码.ARC的第一个关闭,它完美地工作.ARC的下一个打开,BAM崩溃并出现同样的错误.有趣的是,我在崩溃前第一次运行项目时才遇到实际的日志错误.

 Error: ImageIO: ImageProviderCopyImageBlockSetCallback 'ImageProviderCopyImageBlockSetCallback' header is not a CFDictionary...
Run Code Online (Sandbox Code Playgroud)

Lil*_*ard 13

这一行是问题所在:

CGImageRef imageRef = [[[UIImage alloc]initWithContentsOfFile:imagePath]CGImage];
Run Code Online (Sandbox Code Playgroud)

创建的UIImage将在此完整表达后立即释放(例如,在此行之后).因此,即使尝试添加CGImageRetain()后来也无济于事.

根本问题是CGImageRef返回来CGImage的几乎肯定是一个ivar,UIImage并将在UIImage解除分配时释放.

解决这个问题的一般方法是延长生命周期UIImage.您可以通过将其UIImage放入局部变量并在最后一次引用CGImage(例如with (void)uiimageVar)之后引用它来完成此操作.或者,您可以保留CGImageRef在同一行,如

CGImageRef imageRef = CGImageRetain([[[UIImage alloc] initWithContentsOfFile:imagePath] CGImage]);
Run Code Online (Sandbox Code Playgroud)

但是,如果你这样做,不要忘记imageRef在你完成时释放.


rob*_*off 5

你写了这个:

CGImageRef imageRef = [[[UIImage alloc]initWithContentsOfFile:imagePath]CGImage];
Run Code Online (Sandbox Code Playgroud)

该行创建一个UIImage,获取其CGImage属性,然后释放该UIImage对象.既然你没有留CGImage在那条线上,那么唯一的拥有者CGImageUIImage.因此,当UIImage释放并立即解除分配时,它CGImage也会解除分配.

您需要CGImageUIImage发布之前保留.试试这个:

CGImageRef imageRef = CGImageRetain([[UIImage alloc]initWithContentsOfFile:imagePath].CGImage);
Run Code Online (Sandbox Code Playgroud)

然后在函数的末尾:

CGImageRelease(imageRef);
Run Code Online (Sandbox Code Playgroud)