Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS: helpfulness of didReceiveMemoryWarning:

I'm at the part of my development process for tracking down crashing and memory leaks. As a strategy, do you put any NSLog messages or notifications of some such into didReceiveMemoryWarning:? The documentation for this method is rather sparse. Is it accurate to say that before a crash will happen, the UIViewController will trigger that method? Is that a starting point before even going forward with Instruments?

like image 899
Coocoo4Cocoa Avatar asked Feb 24 '09 16:02

Coocoo4Cocoa


3 Answers

UPDATE As of iOS 6, UIViewController views are no longer unloaded in response to memory warnings. Instead just do your best to release any resources you can reasonably re-create (e.g. cached data) when didReceiveMemoryWarning is called.

UPDATE
I wrote my original answer when I was an angry young man; times have changed and basically, it's wrong.

If you have an app with a single view controller and you receive a memory warning, there's not much you can do. But things change dramatically if you have multiple view controllers, because you can unload all the state associated with the non frontmost controllers. In fact [UIViewController didReceiveMemoryWarning] will prod you in the right direction by unloading your non-visible views for you (surprise!). When the frontmost view controller is dismissed, the underlying view is reloaded and at most the user should only be aware of a delay even though internally your app may have done a complete reboot.

This is not some detail you can easily retrofit, you need to keep memory usage in mind from the beginning and design your multiview app into cleanly unloadable UIViewController pieces. In fact it's worth keeping your code compatible with the simulator just to use its memory warning feature.

When memory is abundant, nothing is unloaded and everything is silky smooth, and when memory is low things keep working, albeit more slowly. Now I'd say that this solution to the finite memory problem is ideal.

To take advantage of this memory parlour trick, overload the UIViewController methods viewDidLoad,viewDidUnload, and viewWillUnload (iOS5, useful if unloading state requires your view to still exist, e.g. if you don't want to leak your OpenGL textures & render buffer, on iOS4 you can simulate this by overloading didReceiveMemoryWarning and tracking your view's visibility).

ORIGINAL, MORE BILIOUS ANSWER

didReceiveMemoryWarning is absolutely useless.

There's no guarantee that if you free up memory (even all of it) that you won't get killed.

In my bitter experience it usually works like this on 2.x/3.0:

  1. mediaserverd leaks a bunch of memory

  2. my app gets killed

Unfortunately, the reaper never thinks of killing mediaserverd.

So if the memory usage isn't your fault, you've really only got two choices:

  1. ask the user to reboot (user assumes it's your fault, writes a scathing review)

  2. hope the culprit crashes (mediaserverd often obliges!)

like image 54
Rhythmic Fistman Avatar answered Nov 01 '22 07:11

Rhythmic Fistman


OK, several things to note:

  • didReceiveMemoryWarning will be called before an out-of-memory crash. Not other crashes. If you handle the warning properly and free up memory, then you can avoid the out-of-memory condition and not crash.
  • You can manually trigger a memory warning in the simulator under the Hardware menu. Highly recommend doing this to test your handling of didReceiveMemoryWarning.
  • Instruments helps you debug leaks (though not all of them) - it's not really that useful for crashes.
  • No, I don't personally use NSLog - I just breakpoint the memory warnings when I'm debugging.
like image 34
Airsource Ltd Avatar answered Nov 01 '22 05:11

Airsource Ltd


If the user left some apps open you will have very little memory at your disposal. So sometimes didReceiveMemoryWarning can be called by the system only after 1 MB of usage.

The system calls this method on all your view controllers, if you place a NSLog in each of your view controllers, you will notice that.

Then automatically the method viewDidUnload will be called by the system on all your view controllers (not dealloc). So you have to put all your deallocation instructions in there.

You have to make a lot of experiments because if your app is complex you will face lot of crashes before managing it well.

like image 42
Gianfry Avatar answered Nov 01 '22 05:11

Gianfry