2009-09-09 4 views
17

Si uso [UIImage imageWithCGImage:], pasando un CGImageRef, ¿entonces lanzo el CGImageRef o UIImage se encarga de esto cuando se desasigna?imageWithCGImage y memoria

La documentación no está del todo clara. Dice "Este método no almacena en caché el objeto de imagen".

Originalmente llamé a CGImageRelease en el CGImageRef después de pasarlo a imageWithCGImage:, pero eso provocó una advertencia de malloc_error_break en el Simulador diciendo que se estaba produciendo una doble libre.

+2

Sugiero archivar una falla de documentación en https://bugreport.apple.com/ para pedirles que aclaren esto. –

Respuesta

0

Estoy de acuerdo con usted: la documentación es confusa en el mejor de los casos para esta API. En función de sus experiencias, entonces, concluiría que usted es responsable de la vida útil de ambos objetos: el UIImage y el CGImageRef. Además, debe asegurarse de que la vida útil del CGImageRef sea al menos tan larga como el UIImage (por razones obvias).

0

¿Está utilizando Xcode 3.1 en Snow Leopard? Estoy experimentando el mismo problema:

CGContextRef ctx = ...; 
CGImageRef cgImage = CGBitmapContextCreateImage(ctx); 
UIImage * newImage = [[UIImage imageWithCGImage:cgImage] retain]; 

CGImageRelease(cgImage); // this should be OK, but it now crashes in Simulator on SL 

supongo que la actualización a Xcode 3.2 se solucionará el problema.

+0

A partir de Xcode 8.1, esto funciona para mí. Si no lanzo el 'CGImage', me sale una pérdida de memoria, así que supongo que esta es la manera de hacerlo. – Aderis

4

Tengo el mismo problema en XCode 3.2.1 en Snow Leopard. Tengo prácticamente el mismo código que Jason.

He mirado en el código de ejemplo que utiliza iPhone imageWithCGImage y siempre liberar el CGImageRef usando CGImageRelease después de una llamada a imageWithCGImage.

Entonces, ¿esto es un error en el simulador? Siempre aparece la advertencia malloc_error_break en la consola cuando uso CGImageRelease.

+0

Esto debería ser un comentario sobre la respuesta de Jason, o una nueva pregunta, ya que SO no es un foro. – outis

+0

No puedo comentar las publicaciones de otras personas porque no tengo suficiente "reputación". Además, esta no es una pregunta nueva. Simplemente sugerí que el problema solo podría ocurrir en el simulador pero no en el dispositivo. – Lextar

8

Según el fundamental rule of Cocoa memory management, un objeto propietario debe liberar el objeto propiedad cuando ya no lo necesita. Otros objetos son responsables de tomar y liberar la propiedad por sí mismos. Si un UIImage necesita un objeto para persistir pero no lo retiene o no lo copia, es un error en la implementación de UIImage y debe informarse como tal.

0

<> No es mi opinión. Yo tuve el mismo problema. De acuerdo con la documentación

UIImage *image = [[UIImage alloc] initWithCGImage:imageRef]; 

imho mantiene todas las referencias correctas. Si está utilizando un CGDataProvider, eche un vistazo a CGDataProviderReleaseDataCallback y establezca un punto de interrupción en su devolución de llamada. Puedes ver que se llama correctamente después de que [sueltas] tu imagen y puedes liberar() tu buffer de datos de imagen allí.

0

No estoy seguro de si esto ayuda, pero tuve un problema similar. leí las respuestas y luego hizo lo siguiente que parece haber arreglado:

CGImageRef cgImage = [asset thumbnail]; 
    UIImage *thumbImage = [[UIImage imageWithCGImage:cgImage ]retain]; 
    UIImageView *thumbImageView = [[UIImageView alloc] initWithImage:thumbImage]; 
    CGImageRelease(cgImage); 

he utilizado la autorelease como se sugiere, pero no fue suficiente. Uno que había agregado la imagen al UIImageView, luego lancé el cgImage.
No se bloqueó y desasignó muy bien. Por qué - No tengo idea, pero funcionó.

La miniatura de activos es parte de ALAsset Library, por cierto, es posible que necesite algo más allí.

+0

Parece que está goteando thumbImage aquí, a menos que la suelte en otro lugar. UIImageView.initWithImage: retendrá la imagen. – fishinear

2

La propiedad en UIImage acerca de CGImage no está clara. Parece que no se copia el CGImage pero no está garantizado por la documentación. Así que tenemos que manejar eso nosotros mismos.

Utilicé una nueva subclase de UIImage para manejar este problema. Simplemente reteniendo el pase CGImage, y liberándolo cuando el dealloc.

Aquí está la muestra.

@interface EonilImage : UIImage 
{ 
    @private 
    CGImageRef  sourceImage; 
} 
- (id)initWithCGImage:(CGImageRef)imageRef scale:(CGFloat)scale orientation:(UIImageOrientation)orientation; 

@end 



@implementation  EonilImage 

- (id)initWithCGImage:(CGImageRef)imageRef scale:(CGFloat)scale orientation:(UIImageOrientation)orientation 
{ 
    self = [super initWithCGImage:imageRef scale:scale orientation:orientation]; 

    if (self) 
    { 
     sourceImage = imageRef; 
     CGImageRetain(imageRef); 
    } 

    return self; 
} 
- (void)dealloc 
{ 
    CGImageRelease(sourceImage); 
    [super dealloc]; 
} 
@end 

Debido a que el CGImage devuelto por -[UIImage CGImage] propiedad no se garantiza que sea igual CGImage pasado a método init, las tiendas de clase CGImage por separado.

0
"This method does not cache the image object." 

Así que el UIImage toma la propiedad, y por lo tanto no debe lanzar el CGImageRef.