(iphone) ¿estoy creando una fuga al crear una nueva imagen a partir de una imagen?

Tengo el siguiente código como categoría UIImage + Scale.h.

-(UIImage*)scaleToSize:(CGSize)size
{                                                                                                                                                                                     
  UIGraphicsBeginImageContext(size);

  [self drawInRect:CGRectMake(0, 0, size.width, size.height)];

  // is this scaledImage auto-released?                                                                                                                                                                                        
  UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext(); 

  UIGraphicsEndImageContext();

  return scaledImage;
}

Utilizo la imagen obtenida como arriba y la uso de la siguiente manera.

UIImage* image = [[UIImage alloc] initWithData: myData];
image = [image scaleToSize: size]; <- wouldn't this code create a leak since
                                    image(before scaling) is lost somewhere?

Supongo que los códigos anteriores funcionan bien si la imagen se creó por primera vez con liberación automática.
Pero si la imagen se creó usando 'alloc', crearía una fuga en mi escaso conocimiento.

¿Cómo debo cambiar scaleToSize: para evitarlo?

Gracias

  • EDITAR -

Me gustaría usar alloc (o retener) / release en UIImage para poder mantener el número de UIImage en la memoria en un punto pequeño.
(Estoy cargando muchos UIImages en un bucle y el dispositivo no puede soportarlo)

preguntado el 08 de enero de 11 a las 15:01

2 Respuestas

Tenga en cuenta que su código podría reescribirse como:

UIImage *image = [[UIImage alloc] initWithData:myData];
UIImage *scaledImage = [image scaleToSize:size];
image = scaledImage;

así que veamos qué pasa:

  • image se obtiene a través de alloc, por lo tanto, eres dueño de ese objeto
  • scaledImage se obtiene a través de un método que devuelve un objeto liberado automáticamente ya que UIGraphicsGetImageFromCurrentImageContext() devuelve un objeto liberado automáticamente
  • eres dueño del original image pero no eres dueño scaledImage. Eres responsable de liberar el original. image, de lo contrario tiene una fuga.

En su código, usa una sola variable para referirse a ambos objetos: la imagen original y la imagen escalada. Esto no cambia el hecho de que adueñarnos la primera imagen, por lo tanto, debe liberarla para evitar fugas. Dado que pierde la referencia de la imagen original al usar la misma variable, un modismo común es enviar -autorelease al objeto original:

UIImage *image = [[[UIImage alloc] initWithData:myData] autorelease];
image = [image scaleToSize:size];

O, si prefiere publicar la imagen original en lugar de liberarla automáticamente,

UIImage *image = [[UIImage alloc] initWithData:myData];
UIImage *scaledImage = [image scaleToSize:size];
[image release];
// use scaledImage from this point on, or assign image = scaledImage

En mi opinión, no tiene sentido cambiar scaleToSize:. Es un método de instancia que crea una imagen (liberada automáticamente) basada en una determinada UIImage ejemplo. Es similar a -[NSString stringByAppendingString:], que crea una cadena (una autoliberada) basada en una determinada NSString ejemplo. No le importa ni debería importarle la propiedad de la cadena original, y lo mismo se aplica a su scaleToSize: método. ¿Cómo sabría el método si la persona que llama quiere conservar la imagen original?

Yo también cambiaría el nombre scaleToSize: a imageByScalingToSize para que sea similar a la convención de nomenclatura de Cocoa: obtiene una imagen aplicando una operación a una imagen existente.

Respondido el 08 de enero de 11 a las 19:01

Dado que cuando modifico la imagen, la mayoría de las veces, quiero cambiar la imagen en sí, no crear una nueva. Esperaba cambiar scaleToSize:. Recientemente me di cuenta de que UIImage es un consumidor de memoria bastante grande y quiero mantener pequeño el número de UIImage * en la memoria. o al menos, use alloc / release en lugar de autorelease. - eugene

UIImage es inmutable. No puedes simplemente cambiarlo. Y, excepto si está creando muchas imágenes a la vez, usar un grupo de liberación automática no será muy diferente a enviar -release a mano. Actualizaré la publicación para decirte cómo usar -release en lugar de -autorelease. - usuario557219

Gracias Bavarious, sí, estoy creando muchas imágenes a la vez y quiero manejar la liberación de memoria yo mismo. - eugene

Gracias. Terminé usando alloc / release y creando un grupo de lanzamiento automático / grupo de lanzamiento cuando fue necesario según su sugerencia. La información sobre que UIImage es inmutable también ayudó mucho. - eugene

Sí, seguro que tienes una fuga. El objeto almacenado anteriormente en la imagen ya no se hace referencia pero aún no se desasignó

Respondido el 08 de enero de 11 a las 18:01

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.