tutorial puedo pasar para objective importar guide framework fotos eliminar developer desde con como borrar apple iphone objective-c cocoa-touch memory-management

puedo - pasar fotos de iphone a pc windows 7



Problema dealloc''ing memory utilizado por UIImageViews con una imagen bastante grande en UIScrollView (7)

De lo que aprendí sobre su comportamiento de gestión de memoria es que las vistas no se destrabarán a menos que tengan poca memoria. Pruebe una demostración oficial como SQLBooks: 1. Ejecute con Leaks Monitor 2. Ejecute todas las vistas que tiene. 3. Regrese a la vista raíz. 4. Notará que el nivel de uso de la memoria sigue siendo el mismo. Como Kendall dijo que puede ser almacenado en caché?

Creo que no debe prestar atención a este patrón de uso de la memoria, porque cuando las nuevas imágenes apuntan a UIScrollView, los objetos de la imagen anterior se liberarán y la memoria se liberará para las nuevas imágenes de todos modos.

Tengo un UIScrollView grande en el que estoy colocando 3-4 paneles de imagen UIImageView bastante grandes (320x1500 píxeles o menos). Estoy agregando estos UIImageViews a la vista de desplazamiento dentro de mis archivos NIB. Tengo una salida en mi controlador, y eso es para UIScrollView. Estoy usando una propiedad (no atómica, retener) para esto y lo estoy sintetizando.

Mi pregunta es esta: cuando observo esto en el Monitor de la memoria, puedo ver que la memoria utilizada sube un poco cuando se carga la vista con todas estas imágenes (como se esperaba). Pero cuando dejo la vista, ella y su controlador son desasignados, pero no parecen ceder en ninguna parte cerca de la memoria que habían tomado. Cuando corté una de estas vistas (hay varias en mi aplicación) hasta solo 1-3 imágenes que eran 320x460 y dejé todo lo demás igual, recaptura la memoria muy bien.

¿Hay algún problema con el uso de imágenes de este tamaño? ¿Estoy haciendo algo mal en este código (pegado a continuación)?

Este es un fragmento del viewController que está causando problemas.

- (CGFloat)findHeight { UIImageView *imageView = nil; NSArray *subviews = [self.scrollView subviews]; CGFloat maxYLoc = 0; for (imageView in subviews) { if ([imageView isKindOfClass:[UIImageView class]]) { CGRect frame = imageView.frame; if ((frame.origin.y + frame.size.height) > maxYLoc) { maxYLoc = frame.origin.y; maxYLoc += frame.size.height; } } } return maxYLoc; } - (void)viewDidLoad { [super viewDidLoad]; [self.scrollView setContentSize:CGSizeMake(320, [self findHeight])]; [self.scrollView setCanCancelContentTouches:NO]; self.scrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite; self.scrollView.clipsToBounds = YES; self.scrollView.scrollEnabled = YES; self.scrollView.pagingEnabled = NO; } - (void)dealloc { NSLog(@"DAY Controller Dealloc''d"); self.scrollView = nil; [super dealloc]; }

ACTUALIZACIÓN: He notado otro fenómeno extraño. Si no uso el desplazamiento en la vista, parece estar colgando en la memoria. Pero si me desplazo un poco y me aseguro de que todos los UIImageViews se vuelvan visibles en un punto, se liberarán y recuperarán la mayor parte de la memoria que perdió.

ACTUALIZACIÓN2: La razón por la que estoy preguntando esto es que mi aplicación se está bloqueando debido a la poca memoria. No me importaría si fuera solo el almacenamiento en caché y el uso de memoria extra, pero parece que nunca lo libera, incluso en las condiciones de recuperación de memoria.


He resuelto el misterio, y estoy bastante seguro de que esto es un error del lado de Apple.

Como sugirió Kendall (¡gracias!), El problema radica en cómo InterfaceBuilder carga imágenes del archivo NIB. Cuando inicias FromFromNib, todos los UIImageViews se iniciarán con un UIImage usando el método imageNamed: de UIImage. Esta llamada usa almacenamiento en caché para la imagen. Normalmente, esto es lo que quieres. Sin embargo, con imágenes muy grandes y otras que se desplazan lejos del área visible, no parece estar obedeciendo las advertencias de memoria y volcando este caché. Esto es lo que creo que es un error del lado de Apple (por favor comente si está de acuerdo / en desacuerdo; me gustaría enviar esto si otros están de acuerdo). Como dije antes, la memoria utilizada por estas imágenes parece liberarse si un usuario se desplaza lo suficiente para que todo sea visible.

La solución alternativa que he encontrado (también la sugerencia de Kendall) es dejar en blanco el nombre de la imagen en el archivo NIB. Así que diseñas tus elementos UIImageView de forma normal, pero no seleccionas una imagen. Luego, en su código viewDidLoad, ingresa y carga una imagen usando imageWithContentsOfFile: en su lugar. Este método NO almacena en caché la imagen y, por lo tanto, no causa ningún problema de memoria al conservar imágenes grandes.

Por supuesto, imageNamed: es mucho más fácil de usar, ya que se predetermina a cualquier cosa en el paquete, en lugar de tener que encontrar la ruta. Sin embargo, puede obtener la ruta al paquete con lo siguiente:

NSString *fullpath = [[[NSBundle mainBundle] bundlePath];

Poniendo todo eso a la par, esto es lo que se ve en el código:

NSString *fullpath = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:[NSString stringWithFormat:@"/%@-%d.png", self.nibName, imageView.tag]]; UIImage *loadImage = [UIImage imageWithContentsOfFile:fullpath]; imageView.image = loadImage;

Así que al agregar eso a mi código anterior, la función completa se ve así:

- (CGFloat)findHeight { UIImageView *imageView = nil; NSArray *subviews = [self.scrollView subviews]; CGFloat maxYLoc = 0; for (imageView in subviews) { if ([imageView isKindOfClass:[UIImageView class]]) { CGRect frame = imageView.frame; if ((frame.origin.y + frame.size.height) > maxYLoc) { maxYLoc = frame.origin.y; maxYLoc += frame.size.height; } NSString *fullpath = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:[NSString stringWithFormat:@"/%@-%d.png", self.nibName, imageView.tag]]; NSLog(fullpath); UIImage *loadImage = [UIImage imageWithContentsOfFile:fullpath]; imageView.image = loadImage; } } return maxYLoc; }


- (void)dealloc { NSLog(@"DAY Controller Dealloc''d"); [self.scrollView release]; [super dealloc]; }

dale una oportunidad, tu definición de @property () solicita que se conserve, pero no liberaste explícitamente el objeto


Existe un problema conocido: una pérdida de memoria en imageName. Encontré una solución realmente útil para eso: crear efectivo de imagen en el delegado de la aplicación, optimizando así el rendimiento y el uso de la memoria en mi aplicación. Ver esta publicación en el blog


Separado de su imagen Problemas de almacenamiento en caché, la respuesta a su pregunta

Tengo un UIScrollView grande en el que estoy colocando 3-4 paneles de imagen UIImageView bastante grandes (320x1500 píxeles o menos). [...] ¿Hay algún problema con el uso de imágenes de este tamaño?

Está en el encabezado de los documentos de UIImage:

You should avoid creating UIImage objects that are greater than 1024 x 1024 in size. Besides the large amount of memory such an image would consume, you may run into problems when using the image as a texture in OpenGL ES or when drawing the image to a view or layer.

Además, Apple afirma haber solucionado el problema de descarga de caché imageNamed en 3.0 y más allá, aunque yo no lo he probado extensivamente.


Podría ser que el sistema guarde en el caché las referencias a sus imágenes en la memoria, suponiendo que solo tiene drogas en las imágenes del navegador de medios en IB, el código debajo probablemente esté usando el método UIImage imageNamed : ...

Podría intentar cargar todas las imágenes con imageWithContentsOfFile :, o imageWithData : y ver si se comporta igual (arrastrando UIImageViews sin UIImageViews en IB y configurando contenidos en viewDidLoad :).

Lee la referencia de la clase UIImage si quieres un poco más de detalle, también describe qué métodos están en la memoria caché.

Si es el caché, probablemente esté bien, ya que el sistema lo liberaría si fuera necesario (¿también trataste de simular la advertencia de memoria en el simulador?)


Completando la respuesta de Bdebeez.

Una buena idea es anular imageNamed: llamar a la imageWithContentsOfFile:

Aquí está la idea del código:

@implementation UIImage(imageNamed_Hack) + (UIImage *)imageNamed:(NSString *)name { return [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/%@", [[NSBundle mainBundle] bundlePath], name ] ]; } @end

Nota: Con esta anulación, no tendrá ninguna memoria caché que cargue UIImages; si lo necesita, deberá implementar su propia memoria caché.