Introduction
While developing iPhone applications several times you will get memory level warnings. This tutorial will explain basics and GOOD practices how to handle memory level warnings.
Memory level warnings are logged by SpringBoard.
There are several levels of warnings. These are set from the kernel memory watcher, and can be obtained by the not-so-public function
What should you do when having Memory Level Warning?
Upon receiving any of these warnings, your handler method should respond by immediately freeing up any unneeded memory. For example, the default behavior of the UIViewController class is to purge its view if that view is not currently visible; subclasses can supplement the default behavior by purging additional data structures. An app that maintains a cache of images might respond by releasing any images that are not currently onscreen.
The best practice when you override
Sometimes, however, the necessity of the data may depend on the state of your view. In most cases, those custom data is set in
Therefore, in your
Be careful not to use
That's why it's not a good practice to manually set the
If you mean popping out from a UINavigationController, it actually decrease the retain count of the view controller itself. If the view controller is not retained by another object, it will be deallocated, desirably with its view. As I explained,
How to observe Memory Level warning?
When the system dispatches a low-memory warning to your app, respond immediately. iOS notifies all running apps whenever the amount of free memory dips below a safe threshold. (It does not notify suspended apps.) If your app receives this warning, it must free up as much memory as possible. The best way to do this is to remove strong references to caches, image objects, and other data objects that can be recreated later.
UIKit provides several ways to receive low-memory warnings, including the following:
How to allocate memory wisely?
SEE ALSO
While developing iPhone applications several times you will get memory level warnings. This tutorial will explain basics and GOOD practices how to handle memory level warnings.
Memory level warnings are logged by SpringBoard.
There are several levels of warnings. These are set from the kernel memory watcher, and can be obtained by the not-so-public function
OSMemoryNotificationCurrentLevel()
.typedef enum {
OSMemoryNotificationLevelAny = -1,
OSMemoryNotificationLevelNormal = 0,
OSMemoryNotificationLevelWarning = 1,
OSMemoryNotificationLevelUrgent = 2,
OSMemoryNotificationLevelCritical = 3
} OSMemoryNotificationLevel;
How the levels are triggered is not documented. SpringBoard is configured to do the following in each memory level:- Warning (not-normal) — Relaunch, or delay auto relaunch of nonessential background apps e.g. Mail.
- Urgent — Quit all background apps, e.g. Safari and iPod.
- Critical and beyond — The kernel will take over, probably killing SpringBoard or even reboot.
What should you do when having Memory Level Warning?
Upon receiving any of these warnings, your handler method should respond by immediately freeing up any unneeded memory. For example, the default behavior of the UIViewController class is to purge its view if that view is not currently visible; subclasses can supplement the default behavior by purging additional data structures. An app that maintains a cache of images might respond by releasing any images that are not currently onscreen.
didReceiveMemoryWarning
practices
didReceiveMemoryWarning
releases its view if it is 'safe to do so'. While it's not clear from
Apple's documents what 'safe to do so' means, it is generally recognized
as it has no superview (thus there is no way that the view is currently
visible), and its loadView
method can rebuild the entire view without problems.The best practice when you override
didReceiveMemoryWarning
is, not to try releasing any view objects at all. Just release your
custom data, if it is no longer necessary. Regarding views, just let the
superclass's implementation deal with them.Sometimes, however, the necessity of the data may depend on the state of your view. In most cases, those custom data is set in
viewDidLoad
method. In these cases, 'safe to release custom data' means that you know that loadView
and viewDidLoad
will be invoked before the view controller uses the custom data again.Therefore, in your
didReceiveMemoryWarning
, call the superclass implementation first, and if its view is unloaded, then release the custom data because you know that loadView
and viewDidLoad
will be invoked again for sure. For example,- (void)didReceiveMemoryWarning {
/* This is the view controller's method */
[super didReceiveMemoryWarning];
if (![self isViewLoaded]) {
/* release your custom data which will be rebuilt in loadView or viewDidLoad */
}
}
Be careful not to use
self.view == nil
, because self.view
assumes that the view is needed for someone and will immediately load the view again.viewDidUnload
method
viewDidUnload
is called when the view controller unloaded the view due to a memory warning. For example, if you remove the view from the superview and set the view
property of the controller to nil
, viewDidUnload
method will not
be invoked. A subtle point is that even if the view of a view
controller is already released and set to nil by the time the controller
receives didReceiveMemoryWarning
, so actually there is no view to unload for the controller, viewDidUnload
will be invoked if you call the superclass's implementation of didReceiveMemoryWarning
.That's why it's not a good practice to manually set the
view
property of a view controller to nil. If you do, you may better send a viewDidUnload
message as well. I guess your understanding of viewDidUnload
is more desirable, but apparently it's not the current behavior. - Popping view controllers
If you mean popping out from a UINavigationController, it actually decrease the retain count of the view controller itself. If the view controller is not retained by another object, it will be deallocated, desirably with its view. As I explained,
viewDidUnload
will not be invoked this time.How to observe Memory Level warning?
When the system dispatches a low-memory warning to your app, respond immediately. iOS notifies all running apps whenever the amount of free memory dips below a safe threshold. (It does not notify suspended apps.) If your app receives this warning, it must free up as much memory as possible. The best way to do this is to remove strong references to caches, image objects, and other data objects that can be recreated later.
UIKit provides several ways to receive low-memory warnings, including the following:
- Implement the applicationDidReceiveMemoryWarning: method of your app delegate.
- Override the didReceiveMemoryWarning method in your custom UIViewController subclass.
- Register to receive the UIApplicationDidReceiveMemoryWarningNotificationnotification.
- Eliminate memory leaks.
- Make resource files as small as possible.
- Use Core Data or SQLite for large data sets.
- Load resources lazily.
- Build your program using the Thumb option.
How to allocate memory wisely?
- Reduce your use of autoreleased objects : With automatic reference counting (ARC), it is better to alloc/init objects and let the compiler release them for you at the appropriate time. This is true even for temporary objects that in the past you might have autoreleased to prevent them from living past the scope of the current method.
- Impose size limits on resources : Avoid loading a large resource file when a smaller one will do. Instead of using a high-resolution image, use one that is appropriately sized for iOS-based devices. If you must use large resource files, find ways to load only the portion of the file that you need at any given time. For example, rather than load the entire file into memory, use the mmap and munmap functions to map portions of the file into and out of memory. For more information about mapping files into memory.
- Avoid unbounded problem sets : Unbounded problem sets might require an arbitrarily large amount of data to compute. If the set requires more memory than is available, your app may be unable to complete the calculations. Your apps should avoid such sets whenever possible and work on problems with known memory limits.
SEE ALSO
- http://www.uchidacoonga.com/2009/08/handling-didreceivememorywarning/
- http://iphonedevelopment.blogspot.com/2009/02/clang-static-analyzer.html
- http://www.uchidacoonga.com/2010/12/tips-on-reducing-memory-usage-and-avoiding-didreceivememorywarning/
No comments:
Post a Comment