2010-03-12 6 views
45

He desarrollado una aplicación para iPhone con capacidad de ubicación simple que funciona muy bien según nuestras expectativas, excepto en las condiciones de poca memoria del teléfono.¿Cómo implementar didReceiveMemoryWarning?

En condiciones de poca memoria del teléfono, mi aplicación simplemente se cuelga y si aumenta la memoria del teléfono al liberar algo de espacio, vuelve a funcionar bien sin ningún bloqueo.

cuando busqué en Google el problema encontré que en condiciones de poca memoria el sistema operativo enviará didReceiveMemoryWarning a todos los controladores en la jerarquía actual para que cada uno de ellos implemente el método didReceiveMemoryWarning y también establezca iboutlet en nil para la vista que actualmente no está visible.

También he leído en alguna parte que si la vista de que el controlador no está visible el método setView con el parámetro nil será llamado y si hay algunas variables de salida unidos a ver no habrá problema en la eliminación de ellos.

Así que con todas estas fundas cuál es la mejor manera de manejar condición de memoria de bajo nivel planteado por el Iphone mediante la implementación del didReceiveMemoryWarning y viewDidUnload métodos.

Proporcione un ejemplo o enlace adecuado si es posible para la solución del problema anterior.

gracias.

+0

http://stackoverflow.com/questions/491075/iphone-development-simulate-memory-warning – harshalb

+0

¡Pregunta ejemplar! – bobobobo

Respuesta

20

Un ejemplo He colgado ... lo que he copiado de somwhere ... se le puede dar una idea ...

- (void)didReceiveMemoryWarning { 

    // Release anything that's not essential, such as cached data (meaning 
    // instance variables, and what else...?) 

    // Obviously can't access local variables such as defined in method 
    // loadView, so can't release them here We can set some instance variables 
    // as nil, rather than call the release method on them, if we have defined 
    // setters that retain nil and release their old values (such as through use 
    // of @synthesize). This can be a better approach than using the release 
    // method, because this prevents a variable from pointing to random remnant 
    // data. Note in contrast, that setting a variable directly (using "=" and 
    // not using the setter), would result in a memory leak. 
    self.myStringB = nil; 
    self.myStringD = nil; 
    [myStringA release];// No setter defined - must release it this way 
    [myStringC release];// No setter defined - must release it this way 

    /* 3. MUST CONFIRM: NOT necessary to release outlets here - See override of 
     setView instead. 
    self.labelA = nil; 
    self.imageViewA = nil; 
    self.subViewA = nil; 
    */ 
    // Releases the view if it doesn't have a superview 
    [super didReceiveMemoryWarning]; 
} 
+0

Hey mihir Tengo iboutlets y estoy cargando mi vista desde el archivo de punta simplemente revisa el comentario sobre mi pregunta. Es confuso ya que la vista no es visible, entonces llamará a viewDidUnaload entonces, ¿qué debo hacer anula los valores en didReceiveMemoryWarning o viewDidUNload o setView ???????? – harshalb

+0

pero para cada vista se separará la función didReceiveMemoryWarning para implementar este método con respecto a esa vista particular ... en el método viewDidUnload use el método de acceso correspondiente para establecer el valor del objeto a cero ... –

+0

Hola, estás seguro de que [ super didReceiveMemoryWarning]; necesidad de colocar después de soltar objetos –

5

Depende de usted decidir qué hacer en didReceiveMemoryWarning. El sistema operativo le dice que la memoria es baja y que necesita liberar todo lo que pueda tan pronto como pueda. La idea es que debe liberar todos los datos en caché, descargar las vistas que no están visibles, etc. Los detalles son específicos de la aplicación.

3

También puede liberar memoria en didReceiveMemoryWarning, que se asigna para estática variables en tus clases. Porque una vez que se asigna la memoria para las variables estáticas, no se liberará durante la ejecución de la aplicación.

+1

Hay un pequeño apartado "Advertencias de memoria" en esta página: http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmNibObjects.html – schaechtele

+0

este ahora un día no encontré ningún otro enlace en lugar de eso – codercat

2

Para mi sorpresa, solo unas pocas aplicaciones en las muestras oficiales de iPhone implementan didReciveMemoryWarning. Puede usar el ejemplo de iPhoneCoreDataRecipes como referencia.

Algunas muestras (por ejemplo TableViewSuite) incluso a hacer otra cosa ;-)

14

advertencias de memoria son una señal de que usted debe disponer de los recursos que no son absolutamente críticos. La mayoría de sus controladores se almacenarán en cachés de datos, datos intermedios u otros bits y piezas, a menudo para guardar el recálculo. Cuando reciben advertencias de memoria, deben comenzar a enjuagar todo lo que no necesitan de inmediato para funcionar.

Cómo determinar qué es "crítico" depende completamente del diseño de su aplicación. Un juego OpenGL, por ejemplo, puede determinar que las texturas actualmente en pantalla son valiosas y al ras texturas que no son visibles, o datos de nivel que están fuera de los límites del área de juego actual. Una aplicación con extensos registros de sesión (como un cliente de IRC) puede expulsarlos de la memoria y ponerlos en el disco.

Como observó, la advertencia se envía a cada controlador en su jerarquía, por lo que cada pieza debe determinar individualmente qué datos constituyen "críticos para la operación" y qué constituyen "prescindibles". Si los ha optimizado a todos y sigue recibiendo advertencias de memoria, lamentablemente es hora de volver a visitar el diseño de su aplicación central, ya que está excediendo los límites del hardware.

+0

OK He hecho mi solución haciendo que las salidas sean nulas en mi método viewDidUnload. – harshalb

15

En iOS 5 y versiones anteriores.

Cuando el controlador recibe una advertencia de memoria, se llamará a didReceiveMemoryWarning. En ese momento, si la vista del controlador no está en la jerarquía de vista, la vista se establecerá en nil y viewDidUnload se invocará automáticamente. Entonces, las cosas que debemos hacer en viewDidUnload es liberar la subvista creada en viewDidLoad o creada desde Nib. De esta manera:

- (void)viewDidUnload 
{ 
    self.subView = nil; 
    self.subViewFromNib = nil; 
} 

- (void)didReceiveMemoryWarning 
{ 
    self.someDataCanBeRecreatedEasily = nil; 
    [super didReceiveMemoryWarning]; 
} 

En iOS6.

El controlador no libera automáticamente la vista cuando recibe una advertencia de memoria. Por lo tanto, viewDidUnload nunca se llamará. Pero aún necesitamos liberar nuestra vista (incluida la vista secundaria) cuando ocurre una advertencia de memoria. Me gusta esto.

- (void)didReceiveMemoryWarning 
{ 
    if ([self isViewLoaded] && [self.view window] == nil) { 
     self.view = nil; 
     self.subView = nil; 
     self.subViewFromNib = nil; 
    } 
    self.someDataCanBeRecreatedEasily = nil; 
    [super didReceiveMemoryWarning]; 
} 

Tenga en cuenta que no llamamos a [vista propia] antes de saber que la vista está cargada. porque este método cargará automáticamente la vista si la vista no está cargada.

Tenga en cuenta que podemos liberar la vista solo cuando la vista no se agrega a una ventana.

+1

En realidad, es posible que desee comprobar si '! (! [Self isViewLoaded] || [self.view window] == nil)'. Desea limpiar sus subvistas y otras cosas en cualquier caso. –

Cuestiones relacionadas