didReceiveMemoryWarning advice (too many multitasking applications in the background)? - iphone

Please help, I don't know what I have to do with didReceiveMemoryWarning exactly. My app launched well, but when there is too many running background apps, it receives memory warning, and exit. I just want to show an alert that asks user to exit some background apps.
I have an appDelegate, in its window there is a view of my viewController, it has another view allocated (composite) with two subviews (a XIB over an OpenGL view), and this is set to be a cameraOverlayView in the viewController.
I tried to release the whole stuff in one at warning, but still exited. Do I have to implement didReceiveMemoryWarning in each subview? Can I somehow "forcequit" the initialization process?

If your app is being terminated while it is active, then you probably have a memory leak causing your app to consume a large amount of memory.
When the OS starts running out of memory it will terminate background tasks first starting with the most memory intensive, then eventually the front-most app. The user never needs to manually terminate background apps to save memory. This is all done automatically.
If your app is in the background then it can be terminated at any time. The best you can do is reduce overall memory usage and hope the OS kills some other more memory intensive apps before yours.
didReceiveMemoryWarning is usually where you would release any cached data you have to try and reduce your app's footprint. Any view controllers in your app whose view isn't currently visible will be unloaded and the viewDidUnload method will be called. This is where you should set any IBOutlet properties to nil.
But again if your app is being terminated while it is active, you should use the Leaks tool in Instruments to make sure you don't have any leaks and you aren't consuming an abnormally large amount of memory.

Related

When is didReceiveMemoryWarning actually called

I've never personally seen didReceiveMemoryWarning called before. Is there a known threshold of memory usage where it gets called?
It's called when the system has low memory, then you need to purge your UIViewController.
You can simulate a memory warning in the Simulator: Hardware > Simulate Memory Warning and see what happens.
If you are supporting prior versions to iOS6 it's important to take note of the following from Apple's documentation:
Prior to iOS 6, when a low-memory warning occurred, the
UIViewController class purged its views if it knew it could reload or
recreate them again later. If this happens, it also calls the
viewWillUnload and viewDidUnload methods to give your code a chance to
relinquish ownership of any objects that are associated with your view
hierarchy, including objects loaded from the nib file, objects created
in your viewDidLoad method, and objects created lazily at runtime and
added to the view hierarchy. On iOS 6, views are never purged and
these methods are never called. If your view controller needs to
perform specific tasks when memory is low, it should override the
didReceiveMemoryWarning method.
About the threshold, I try not to exceed 12MB of memory.
No. It is called when springboard feels that there are too many resources using memory on the device. Depending on how much stuff other apps are using on your phone, it can happen sooner or later. You can never reliably calculate or rely on when it will happen.
Also be warned, because the memory reported in tools like allocations is not necessarily correlated to the footprint of your app, so it can look like you are not using much, but you may still get this warning.
from the documentation , when the system determines that the amount of available memory is low then this method is called. system determines low memory itself , when your app allocations exceed the amount of memory available to your app then this method is called. Please refer http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html

App is locking up iOS but no memory leaks are reported

Having a strange issue with my app where the entire iOS device gets locked up and the only thing I can do is restart the device. I am not seeing any exceptions getting thrown, nor am I seeing any memory leaks in Instruments.
The app has a navigation controller with a main menu. I then push a viewcontroller that has a grid of images being loaded. If I go back and forth between the main menu and the grid the app will crash after ~15 times. However, it isn't just the app that's killed, it's the entire OS which is something I've never seen.
At first I thought I was leaking memory, but Leaks isn't showing anything. I'm playing around with Allocations and I'm seeing that the grid view controller allocation count just keeps going up. The app is using ARC, which I don't like that much because it's too "magical", but I assumed it would be cleaning up properly.
One thing that concerns me is that viewDidUnload nor dealloc is being called on my grid view controller after it popped from the nav controller, so I'm never explicitly cleaning up my images or killing network connections. I assume this is where the issue is at but I don't know when I should kill these because the usual places to clean up (ie. viewDidUnload, dealloc) aren't being called.
This is happening on iPhone and iPad both running 5.1 and I'm using the AFNetworking UIImageView category to load images.
Cheers,

What to do when my app receives memory warning?

What should I do when my app recieves a memory warning?
It all depends on your app, usually you don't have to do anything special except following Apple's recommended practices.
ViewControllers which are not visible at the moment will get didReceiveMemoryWarning message. By default (calling [super didReceiveMemoryWarning]) controller's view is unloaded (released, freed). As the view is unloading, view controller receives viewDidUnload where you should release all your IBOutlets (or otherwise retained UI elements). Only then the view can completely be deallocated and memory freed.
In the didReceiveMemoryWarning you should also free as much data as you can - if you store some part of data model in ViewController, release it, and reconstruct in viewDidLoad that would be called when your view is loaded again (when user navigates back to this controller). You can inform your model classes to free memory too.
It really depends on your app.
If your app downloads and caches lots of contents from Internet for example, you should purge as much as possible when receiving a warning.
If your app is an OpenGL game, you might have a texture/sound/data manager which references some unused data, which you then want to free. Cocos2D manages this kind of things.
If your app isn't memory intensive, you have a memory leak somewhere, and you should 1) read the Memory Management Programming Guide by Apple 2) use Instruments/Leaks.
In didReceiveMemoryWarning, you should release any cached or non-essential items to prevent running out of memory completely.
If you log or write to any other file, there might be an issue with "disk" space.
Also you should check for memory leaks.

Why bother with releasing memory in viewDidUnload and dealloc

Aren't these methods called when the app is about to be shut down? If so, then won't the memory be all cleared out anyway?
If you only have one view that lasts the duration of the app, then unload and dealloc are currently never even called, so these methods are actually unused and unneeded.
However, if you ever expand this app to have views and objects that get switched in and out of use, then in low memory circumstances these methods may well be called to lower your app's memory footprint so that the app doesn't get killed for using too much memory. So leaving them in (and coding them correctly to release internally allocated objects and malloc'd memory) for future code reuse is considered good practice. That's why they come with the various Cocoa templates.
Aren't these methods called when the app is about to be shut down? If so, then won't the memory be all cleared out anyway?
It is true that viewDidUnload and dealloc are called when an app terminates, but these are certainly not the only times. It is very important to correctly implement these cleanup methods, as well as didReceiveMemoryWarning.
If you don't clean up properly in dealloc, then your app will start to leak memory. Over time, it may consume more and more memory, until it gets terminated by the system.
Similarly, if your viewDidUnload doesn't release its resources, you can be leaking memory. If the view is used multiple times, each invocation will leak.
Careful memory management is more important than ever with iOS 4, as your application may end up in the background if the user presses the Home button. This means it may run for longer than ever, and thus you will be reusing the same view controllers when it regains the foreground. If your app doesn't release unused memory properly, it will almost certainly be killed by the system.
iOS Memory Management Programming Guide
viewDidUnload is only called in low memory situations. You want to release all object you create in viewDidLoad. You want to pair them up. You still want to release everything in dealloc, since viewDidUnload will not be called if low memory situations never occur in your app.
Keep in mind that each class inerithing from NSObject has its dealloc and so when the reference count of an object reaches 0 , its dealloc is being called, meaning that the memory owned by that object would better be deallocated.
Similarly viewDidUnload is a method that each UIViewController has and it is being called when the main view associated to the controller is no more needed, no more visible if you want (you can think of it being called when you a pop the controller from a navigation stack or switch a tab in tabbar controller). It is convenient for the app and the iPhone/iPod not to have the objects owned by the view around when the view is not displayed/active/used etc.
Finally the AppDelegate, as an object has its own dealloc method, so maybe your confusion can come from this point.

iPhone rotation causes memory warning

I am introducing auto-rotation to my app and I'm having an issue with a memory warning. Whatever orientation I start my app in, as long as the device remains in that orientation, I get no memory warnings. However, the first time I rotate the device the following warning is placed on the console: Safari got memory level warning, killing all documents except active. When this happens all view controllers, other than the one be viewed, are unloaded - this produces unexpected behaviors when navigating back to view controllers that should normally already be on the stack. The app never crashes and this warning occurs once upon the first rotation, after that it never happens (until I stop/start the app again). Also, this only happens on the device - no memory warning when running in simulator.
Has anyone seen this behavior? In any case, does anyone have any suggestions on what I might try in order to remove the memory warning.
Thanks in advance.
You can't assume that memory warnings will never happen; you have to handle them gracefully. Suggestions:
Check for memory leaks with Leaks (note that it doesn't catch all leaks).
Fix your view controllers to handle a view reload. Specifically (unless you override -(void)loadView), it'll call -(void)viewDidUnload on a memory warning and -(void)viewDidLoad when it becomes visible again. You might fix this by saving state in the view controller and restoring it to the views in -(void)viewDidLoad.
If you can't be bothered handling the memory warning, implement -(void)didReceiveMemoryWarning and do not super-call (i.e. comment out [super didReceiveMemoryWarning]). This is lazy, and might cause a crash if your app ends up using too much memory (background apps like Safari and Phone will be killed first).
You can test memory warning behaviour with the "simulate memory warning" option in the simulator.
Memory warnings are part of a normal iOS behavior, due to its limited memory, especially now that multi-tasking is supported.
UIKit doesn’t only allow navigation back from a view controller, but also allows navigation to other view controllers from existing ones. In such a case, a new UIViewController will be allocated, and then loaded into view. The old view controller will go off-screen and becomes inactive, but still owns many objects – some in custom properties and variables and others in the view property/hierarchy. And so does the new visible view controller, in regard to its view objects.
Due to the limited amount of memory of mobile devices, owning the two sets of objects – one in the off-screen view controller and another in the on-screen view controller – might be too much to handle. If UIKit deems it necessary, it can reclaim some of the off-screen view controller’s memory, which is not shown anyway; UIKit knows which view controller is on-screen and which is off-screen, as after all, it is the one managing them (when you call presentModalViewController:animated: or dismissModalViewControllerAnimated:). So, every time it feels pressured, UIKit generates a memory warning, which unloads and releases your off-screen view from the view hierarchy, then call your custom viewDidUnload method for you to do the same for your properties and variables. UIKit releases self.view automatically, allowing us then to manually release our variables and properties in our viewDidUnload code. It does so for all off-screen view controllers.
When the system is running out of memory, it fires a didReceiveMemoryWarning. Off-screen views will be reclaimed and released upon memory warning, but your on-screen view will not get released – it is visible and needed. In case your class owns a lot of memory, such as caches, images, or the like, didReceiveMemoryWarning is where you should purge them, even if they are on-screen; otherwise, your app might be terminated for glutting system resources. You need to override this method to make sure you clean up your memory; just remember you call [super didReceiveMemoryWarning];.
An even more elaborate explanation is available here: http://myok12.wordpress.com/2010/11/30/custom-uiviewcontrollers-their-views-and-their-memory-management/