UIImage de CGImageRef

Estoy probando una testing simple para un proyecto mucho más complejo, pero estoy desconcertado acerca de por qué el código siguiente se bloquea y da un error EXC_BAD_ACCESS.

Esto se llama desde una 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]; } 

Mi conjetura es que el CGImageRef no se retiene pero agrega CGImageRetain (imageRef); No hace diferencia.

También debería notar que este proyecto tiene activado ARC.

EDITAR

Hice un poco más de testings y he descubierto que esto está directamente relacionado con ARC, ya que creé 2 proyectos básicos que incluyen solo el código anterior. El primero con ARC apagado y funcionó perfectamente. El siguiente con ARC activado y BAM se bloquea con el mismo error. Lo interesante es que obtuve un error de logging real SÓLO la primera vez que ejecuté el proyecto antes del crash.

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

Esta línea es el problema:

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

El UIImage creado se lanzará inmediatamente después de esta expresión completa (por ejemplo, después de esta línea). Entonces, incluso tratar de agregar un CGImageRetain() luego no funcionará.

El problema fundamental es que el CGImageRef devuelto desde CGImage es casi seguro un ivar del UIImage y se liberará cuando se invoque el UIImage .

La forma genérica de solucionar esto es extender la vida útil del UIImage . Puede hacer esto colocando UIImage en una variable local y haciendo reference a él después de su última reference a CGImage (por ejemplo, con (void)uiimageVar ). Alternativamente, puede conservar el CGImageRef en esa misma línea, como en

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

Pero si haces esto, no olvides liberar imageRef cuando hayas terminado.

Escribiste esto:

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

Esa línea crea un UIImage , obtiene su propiedad CGImage y luego libera el object UIImage . Como no CGImage la CGImage en esa línea, el único propietario de CGImage es el UIImage . Entonces, cuando el UIImage se libera y se desasigna inmediatamente, desasigna también el CGImage .

CGImage conservar el CGImage antes de CGImage el UIImage . Prueba esto:

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

y luego al final de la function:

 CGImageRelease(imageRef);