2011-02-25 10 views
13

Estoy tratando de crear vistas previas de imágenes en un PDF , pero tengo algunos problemas con el lanzamiento de la memoria.UIGraphicsGetImageFromCurrentImageFalda de memoria de contexto con vistas previas

escribí un algoritmo simple prueba de que los ciclos en el problema, la aplicación se bloquea cerca de la iteración 40a:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
NSString *documentsDirectory = [paths objectAtIndex:0]; 
NSString *pdfPath = [documentsDirectory stringByAppendingPathComponent:@"myPdf.pdf"]; 
CFURLRef url = CFURLCreateWithFileSystemPath(NULL, (CFStringRef)pdfPath, kCFURLPOSIXPathStyle, NO); 
CGPDFDocumentRef myPdf = CGPDFDocumentCreateWithURL(url); 
CFRelease (url); 
CGPDFPageRef page = CGPDFDocumentGetPage(myPdf, 1); 

int i=0; 
while(i < 1000){ 

    UIGraphicsBeginImageContext(CGSizeMake(768,1024)); 
    CGContextRef context = UIGraphicsGetCurrentContext(); 
    CGContextSetRGBFillColor(context, 1.0,1.0,1.0,1.0); 
    CGContextFillRect(context,CGRectMake(0, 0, 768, 1024)); 
    CGContextSaveGState(context); 
    CGContextTranslateCTM(context, 0.0, 1024); 
    CGContextScaleCTM(context, 1.0, -1.0); 
    CGContextDrawPDFPage(context, page); 
    CGContextRestoreGState(context); 

    // -------------------------- 
    // The problem is here (without this line the application doesn't crash) 
    UIImageView *backgroundImageView1 = [[UIImageView alloc] initWithImage:UIGraphicsGetImageFromCurrentImageContext()]; 
    // -------------------------- 

    UIGraphicsEndImageContext(); 
    [backgroundImageView1 release]; 

    NSLog(@"Loop: %d", i++); 
} 

CGPDFDocumentRelease(myPdf); 

La línea mencionada parece generar una pérdida de memoria, sin embargo, los instrumentos no muestran problemas de memoria;

¿Puedo escapar de este tipo de error? ¿Alguien me puede explicar de qué manera? ¿Hay otras maneras de mostrar vistas previas de un pdf?

ACTUALIZACIÓN

creo que el problema no es la liberación de UIImage creado por el método UIGraphicsGetImageFromCurrentImageContext() pero la liberación de UIImageView creado con esta imagen autorelease.

He dividido la línea de código en tres pasos:

UIImage *myImage = UIGraphicsGetImageFromCurrentImageContext(); 
UIImageView *myImageView = [[UIImageView alloc] init]; 
[myImageView setImage: myImage]; // Memory Leak 

La primera y segunda líneas no crea pérdidas de memoria por lo que creo que el método UIGraphicsGetImageFromCurrentImageContext no es el problema.

También probé la siguiente manera pero el problema persiste:

UIImageView *myImageView = [[UIImageView alloc] initWithImage:myImage]; 

Creo que hay una pérdida de memoria en la liberación de un UIImageView que contiene una UIImage con la propiedad autorelease.

Intenté escribir mi objeto UIImageView heredando una UIView como se explica en este thread.

Esta solución funciona pero no es muy elegante, es una solución, preferiría usar el objeto UIImageView para resolver el problema de memoria.

+0

¿Qué instrumentos está utilizando para controlar el uso de la memoria? Vería "asignaciones" y "monitor de actividad", que pueden mostrar el uso de memoria que el instrumento de fugas omite. Además, ¿qué se supone que está haciendo este código de todos modos? ¿Desea crear 1000 vistas de imágenes pero luego deshacerse de ellas sin usarlas? –

+0

¿Has encontrado la respuesta? Tengo el mismo problema: S –

Respuesta

1

¿Este código se ejecuta en el hilo principal? La documentación de UIGraphicsGetImageFromCurrentImageContext (link) dice que debe ejecutarse de esa manera.

+0

Sí, he leído la documentación de Apple. Llamo a esta función en el hilo principal, gracias de todos modos por su respuesta! – Alessandro

+8

De la última documentación de UIKit en 'UIGraphicsGetImageFromCurrentImageContext':' En iOS 4 y posterior, puede llamar a esta función desde cualquier subproceso de su aplicación. – chown

23

El problema es el siguiente:

UIGraphicsGetImageFromCurrentImageContext() 

devuelve un autoreleased UIImage. El grupo de liberación automática conserva esta imagen hasta que el código devuelve el control al runloop, lo que no hace durante mucho tiempo. Para resolver este problema, debería crear y drenar un grupo de autorelease nuevo en cada iteración (o cada pocas iteraciones) de su ciclo while.

+2

Intenté crear y liberar NSAutorelease Pool en cada iteración, pero el problema de memoria persiste. ¡Gracias de todos modos por su respuesta! – Alessandro

+0

¿Obtuviste alguna solución? – spd

+0

funcionó para mí. ¡Gracias por el consejo! – pstoppani

-1

su línea de accidente que puede actualizarlo como seguir

y llévese un UIImage fuera del bucle

rendered_image = UIGraphicsGetImageFromCurrentImageContext();

9

Sé que es una vieja pregunta, pero hace unas horas me golpeo la cabeza contra la pared. En mi aplicación llamando repetidamente

UIImage *image = UIGraphicsGetImageFromCurrentImageContext() 

en un bucle no aferrarse a la memoria a pesar de llamarme imagen = nil; No estoy seguro de cuánto tiempo la aplicación mantendrá la memoria antes de liberarla, pero ciertamente es lo suficientemente larga como para que mi aplicación reciba una advertencia de memoria y luego se cuelgue.

Pude resolverlo finalmente envolviendo el código que llama/usa la imagen de UIGraphicsGetImageFromCurrentImageContext() en @autoreleasepool. Así que tengo:

@autoreleasepool { 
    UIImage *image = [self imageWithView:_outputImageView]; //create the image 
    [movie addImage:image frameNum:i fps:kFramesPerSec]; //use the image as a frame in movie 
    image = nil; 
} 

la esperanza de que pudiera ayudar a alguien.

+0

¡esto fue todo para mí! gracias :) – davvilla

Cuestiones relacionadas