renderincontext Memory Fuga si no se usa en el hilo principal

Estoy intentando convertir mi UIView en UIImage utilizando el código siguiente.

+ (UIImage *) imageWithView:(UIView *)view{ float scale = 1.0f; UIGraphicsBeginImageContextWithOptions(view.bounds.size, YES, scale); [view.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage* img = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); view.layer.contents = nil; return img; } 

Hay dos problemas con este código.

1. Cuando ejecuto este código en el hilo de background (! MainThread)

Me enfrenté a un problema de pérdida de memory cuando se llama a renderInContext en el hilo de background.

2. Cuando ejecuto este código en el hilo principal

No hay pérdida de memory, pero en iPad 3 estoy enfrentando algún problema de performance (mi interfaz de usuario se cuelga cuando se llama a este método) mientras se crea una image desde UIView. Como necesito llamar a esta function más de 5 veces en segundos, la interfaz de usuario se cuelga y da una experiencia de usuario muy mala.

¿Por favor, guíame si estoy haciendo algo mal aquí?

Creo que el problema 1 está relacionado con el hecho de que UIKit no es seguro para subprocesss y su uso dará lugar a todo tipo de efectos secundarios.

Si tiene un problema de performance como el que está describiendo, el único path que veo es directamente usar CoreGraphics (no UIKit) en un hilo secundario.

Puede probar algo como esto, como un comienzo:

 size_t width = view.bounds.size.width; size_t height = view.bounds.size.height; unsigned char *imageBuffer = (unsigned char *)malloc(width*height*4); CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB(); CGContextRef imageContext = CGBitmapContextCreate(imageBuffer, width, height, 8, width*4, colourSpace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little); CGColorSpaceRelease(colourSpace); [view.layer renderInContext:imageContext]; CGImageRef outputImage = CGBitmapContextCreateImage(imageContext); CGImageRelease(outputImage); CGContextRelease(imageContext); free(imageBuffer); 

Como puede ver, esto es bastante más complejo que el modo UIKit , pero se puede ejecutar en un subprocess secundario (siempre que encuentre una manera de pasar el outputImage a su subprocess de interfaz de usuario que no se muestra).

Acabo de haberme sucedido esto (pérdida de memory debido a renderInContext ) en el hilo principal . Estuve recorriendo cientos de vistas fuera de la pantalla, convirtiéndolas en objects UIImage y guardándolos como files PNG. Lo que resolvió el problema para mí fue envolver las entrañas de mi ciclo en un bloque @autoreleasepool :

Roto:

 for (...) { ...render layer in context... ...save image to disk... } 

Trabajos:

 for (...) { @autoreleasepool { ...render layer in context... ...save image to disk... } } 

Tiene sentido, ¿verdad?