versiones mini instalar descargar como ios memory-management ipad-3

ios - mini - El nuevo iPad: ¿Advertencias de memoria baja no aparecen?



ios 9 (6)

He estado desarrollando una aplicación para iPad que es muy gráficamente intensiva. He podido exprimir un poco de rendimiento en el iPad 2, pero los gráficos @ 2x para el nuevo iPad tienen un gran impacto en el departamento de memoria. Usando el Monitor de actividad en instrumentos, puedo ver cómo el tamaño de mi aplicación aumenta rápidamente en el rango de 300MB a 400MB, pero no recibo ninguna notificación de poca memoria. Estoy usando un UINavigationController para administrar mis vistas, por lo que bajar a la pila tiene un efecto acumulativo en la memoria que termina en su finalización. No experimento este problema en el iPad 2, donde recibo notificaciones de poca memoria como se esperaba. Mi aplicación se ha codificado para limpiar tanto como sea posible y funciona muy bien en ese dispositivo.

He leído una serie de preguntas similares:

Aplicación iOS matada por memoria baja pero no se recibió ninguna advertencia de memoria
¡La aplicación de iPhone usa 150 MB de memoria y todavía no hay poca advertencia de memoria!

Ninguna de las sugerencias parece ayudar.

He insertado el código para forzar el envío de una notificación de poca memoria:

[[UIApplication sharedApplication] _performMemoryWarning];

Esto hace que las vistas inactivas se descarguen como se espera y devuelve el consumo de memoria a la normalidad. Esto utiliza una API privada y es un hack, por lo que por razones prácticas no es una solución. ¿Cómo hago para que mi dispositivo responda adecuadamente a las condiciones de poca memoria y le informo a mi aplicación que necesita limpieza?


El siguiente es mi experiencia. Estoy muy feliz de que me corrijan ...

¿Cómo estás cargando tus imágenes?

Si estás usando:

[UIImage imageNamed:(NSString *)]

Entonces debes asegurarte de que haya una buena razón para hacerlo. Si está haciendo un uso intensivo de una imagen que debe almacenarse en caché, entonces es una buena opción. De lo contrario, te sugiero que uses

[UIIMage imageWithContentsOfFile:(NSString *)]

Parece que iOS tiene algunos problemas al lanzar imágenes cargadas a través de imageNamed, incluso si ya no hay referencias a él. Dado que su aplicación ya no tendrá ninguna referencia a la imagen, es probable que no reciba las advertencias de memoria. Pero eso no significa que la memoria haya sido liberada. iOS tiende a mantener estas imágenes en la memoria mucho más tiempo del que te gustaría. Cuando normalmente daría una advertencia de memoria, simplemente terminará la aplicación.

También recomendaría encarecidamente activar el conteo automático de referencias (ARC).

Edit -> Refactor -> Convert to Objective-C ARC...

Tuve problemas similares durante bastante tiempo. Hacer los cambios anteriores en mi aplicación detuvo los bloqueos y detuvo la pérdida de memoria causada cuando volví a cargar la misma imagen una y otra vez a través de imageNamed.

Espero que ayude.


He estado trabajando en la aplicación que consume mucha memoria y mis sugerencias son:

  1. Use alloc - init y release , evite el uso de objetos de liberación automática.
  2. Verificar fugas de memoria
  3. Si necesita utilizar el objeto de liberación automática, use NSAutoreleasePool antes de crear el objeto y drene el grupo cuando haya terminado el trabajo con el objeto.
  4. Si está utilizando OpenGL, recuerde eliminar todos los objetos creados, especialmente texturas
  5. Tal vez deberías intentar cambiar a ARC

Me parece que el problema es que tus imágenes no se están lanzando. De acuerdo con la documentación de UIImage (y mi experiencia), imageNamed: almacena en caché las imágenes que carga. Por lo tanto, debe usarlo para iconos pequeños o imágenes que se usan casi constantemente, pero generalmente es una mala idea usarlo para imágenes grandes o imágenes que se usan con poca frecuencia. Como dice user499177, debe usar imageWithContentsOfFile: (puede usar los [NSBundle mainBundle] para derivar la ruta) en su lugar:

Este método busca en el caché del sistema un objeto de imagen con el nombre especificado y lo devuelve si existe. Si un objeto de imagen coincidente no está ya en la memoria caché, este método carga los datos de imagen del archivo especificado, lo almacena en la memoria caché y luego devuelve el objeto resultante.


Contacté al Soporte de Apple para resolver mi problema de memoria y pregunté sobre las advertencias de memoria baja en el iPad 3:

-Porque las advertencias de memoria se entregan en el hilo principal, su aplicación no recibirá advertencias de memoria si está bloqueando el hilo principal.

- Incluso si su aplicación no está bloqueando el hilo principal, es posible que el uso de la memoria crezca lo suficientemente rápido como para que las advertencias de memoria no se entreguen antes de que su aplicación muera para liberar memoria.

- Las advertencias de memoria se activan cuando el kernel hace una transición entre varios niveles de presión de la memoria. Debido a esto, es común que una aplicación reciba una advertencia de memoria y luego muera bastante tiempo después cuando la memoria se agote. La advertencia de memoria inicial liberó suficiente memoria para mantener viva la aplicación, pero no lo suficiente para que el kernel pase a un nivel más bajo de presión de memoria.

Debido a todo esto, la advertencia de memoria debe tratarse como datos útiles sobre el estado del hardware y una buena guía sobre la cantidad de memoria que su aplicación debería usar en un dispositivo determinado, pero no debe considerarse una herramienta para evitar su aplicación. de ser asesinado.

Tal vez esto ayude ...


Este problema se solucionó en iOS 5.1.1. Para aquellos usuarios que están en 5.1, he implementado mi propio guardián de memoria y envío una notificación similar a la utilizada cuando se emite una advertencia de memoria real.

Primero creé una categoría en UIApplication . Esto publica una notificación que UIImage escucha (o lo que sea su caché de respaldo) para descargar imágenes en caché.

.marido

@interface UIApplication (ForceLowMemory) + (void) forceUnload; @end

.metro

#import "UIApplication+ForceLowMemory.h" @implementation UIApplication (ForceLowMemory) + (void)forceUnload { [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidReceiveMemoryWarningNotification object:[UIApplication sharedApplication]]; } @end

Luego, creé un watchdog de administrador de memoria como el siguiente:

.marido

@interface ELMemoryManager : NSObject - (void)startObserving; - (void)stopObserving; + (ELMemoryManager*) sharedInstance; @end

.metro

#import "ELMemoryManager.h" #import "UIApplication+ForceLowMemory.h" #import <mach/mach.h> @interface ELMemoryManager() @property (nonatomic, retain) NSTimer *timer; uint report_memory(void); @end #define MAX_MEM_SIZE 475000000 @implementation ELMemoryManager @synthesize timer = timer_; static ELMemoryManager* manager; #pragma mark - Singleton + (void) initialize { if (manager == nil) { manager = [[ELMemoryManager alloc] init]; } } + (ELMemoryManager*) sharedInstance { return manager; } #pragma mark - Instance Methods uint report_memory(void) { struct task_basic_info info; mach_msg_type_number_t size = sizeof(info); kern_return_t kerr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size); if( kerr == KERN_SUCCESS ) { return info.resident_size; } else { return 0; } } - (void)startObserving { if (!self.timer) { NSTimer* timer = [NSTimer scheduledTimerWithTimeInterval:5.0f target:self selector:@selector(checkMemory:) userInfo:nil repeats:YES]; self.timer = timer; } [self.timer fire]; } - (void)stopObserving { [self.timer invalidate]; self.timer = nil; } - (void)checkMemory:(id)sender { uint size = report_memory(); if (size > MAX_MEM_SIZE) { NSLog(@"we''ve busted the upper limit!!!"); [UIApplication forceUnload]; } } #pragma mark - Memory Management - (void)dealloc { [self.timer invalidate]; [timer_ release]; [super dealloc]; } @end


Mega-Dittos. Esto ha sido muy tranquilizador. Yo también estoy haciendo una aplicación de imagen intensiva (muchos objetos UIImage en UIImageView para animación) y tengo el código de advertencia de memoria habitual en mi delegado de aplicación, pero nunca se dispara. Sin embargo, Instruments mostró el problema cuando cargué imágenes, dibujé sobre ellas y las envié a las imágenes. Estoy usando ARC, me deshice de las filtraciones de CGImageRef y similares, pero al final del día si cargas suficientes imágenes en un ImageView, con la suficiente rapidez obtendrás un bloqueo sin advertencia de ningún tipo en el registro, la aplicación delegar callback de método, o instrumentos. La aplicación simplemente saca la alfombra de debajo sin siquiera un "por tu permiso".

Aún no he tenido la oportunidad de probar esto en un iPad2 pero, independientemente de ello, es necesario que haya ALGUNA indicación, al menos un mensaje de consola minimalista o algo así. La mayor parte de la carga ocurre en mi propia cola de GCD, no en el hilo principal, aunque por definición las actualizaciones de los controles de pantalla tienen que hacerse en el hilo principal. Así que supongo que si eso está bloqueando cuando la carrera está a punto de ser retirada, entonces supongo que puedes obtener una falla anónima. Sin duda, esto ayudaría a obtener ALGUN tipo de mensaje de consola.