iPhone - How to deal with low memory conditions

3.3k views Asked by At

When the app receives a low memory warning message, 3 situations can happen :

  1. your app has just been launched and the user has not done anything special
  2. the app is running and there is a current context
  3. the app is in the background with some running context

So when you receive this message, your are supposed to free memory... But where ? And how ?

I understand that :

  1. initWith..... must set the default static values.
  2. viewDidLoad must load any non static object
  3. didReceiveMemoryWarning must free those non static objects
  4. I don't see what can/must be done in viewDidUnload...

I guess some retained values must be set to nil somewhere... in didReceiveMemoryWarning ?

And what must be done with the active context (positions of thing of the screen, displayed text, ...) so when viewDidLoad is called again, those thing appear again as they where before the memoryWarning call ?

I mean, imagine 2 scenarios :

Scenario 1

  1. you are working on something... you wrote some text in a field, did not saved it, opened another view, moved a view on the screen.
  2. You send the app in background.
  3. Then a memoryWarning is sent to the app.
  4. After that, the user send the app to foreground : it should display things like they was on exit, on the current view as on previous views, but if everything has been released, how may you do this ?

Scenario 2

  1. you are working on something... you wrote some text in a field, did not saved it, opened another view, moved a view on the screen.
  2. Then a memoryWarning is sent to the app.
  3. You don't want to loose what is on the view, nor what was on the previous view. You don't want neither the screen to flicker because of a release / reload feature. How do you deal with this ?

So when those memory warning happens, do you have any other choice than writing things to disk to display them back later ?

And when do you load those again ? I have a viewController that loads (viewDidLoad), receive a memoryWarning, unloads (viewDidUnload), but when going back to it, viewDidLoad is not called again ? Do this must be done in viewWillAppear ? Do I have to think that anytime viewWillAppear is triggered, I can assume that things that are supposed to be displayed on it are loaded ?

Any help, even with valuable links, would be great !

Thank you for your help.

2

There are 2 answers

1
hotpaw2 On

Consider the alternatives to your scenarios. Your app could be killed if it does not free enough memory, which would be even more jarring to the user. One might choose potentially flickering the current display over losing the user's valuable data.

0
Giuseppe Garassino On

My idea is that two methods are called when an app receives a low memory warning:

didReceiveMemoryWarning // in your NSObjects

and

applicationDidReceiveMemoryWarning // in your app delegate

then, if you want to free memory, these are the methods to consider.

As regards what you can do in there... Well... Think about what Xcode suggests:

- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
    /*
     Free up as much memory as possible by purging cached data objects that can be recreated (or reloaded from disk) later.
     */
}

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

Seemingly, the best choise will be freeing any object not seen by the user and/or not in use, or any cached data that you can recreate later. Do not touch your GUI: if you close it or part of it your app becomes unusable and the user disappointed.

Regarding your 2 scenarios, I see a possible mistake in considering what memory warning are for. They are a way to treat an emergency and not the normal way to manage memory. Developpers must think of a good memory architecture and save data whenever possible.

In scenario 1, save your data when the app is sent to background.

applicationDidEnterBackground

In scenario 2, save your data when a new view is opened.

Hope this makes sense...