I have a few tabs in my app. I am currently facing an issue whereby my pages gets unloaded whenever the memory gets low (especially if I bring up the camera in my app).
Is there anyway to mitigate this and prevent unloading from happening? Or is there any way to intercept the unloading process so that something can be done instead of allowing the page to be unloaded?
You should not prevent view unloading, if the application runs out of memory, it MUST free memory, or else your app will simply be killed by the system. You should really cleanup as much memory as you can, as well as views.
Also, views are only there to display data, if the view is unloaded it's only in one specific case: there was a memory warning and the view didn't have a superview (not visible to the user). If it's not visible to the user, it makes absolutely no sense to keep it around when running out of memory. If you're storing [important] data in these views, you're doing it wrong. Data model should be kept in controllers.
When the memory gets low, all the view controllers get their delegate method: didReceiveMemoryWarning called.
The default implementation of UIViewController is to unload the view.
So, all you need to do in order to override this behavior is override the method:
- (void)didReceiveMemoryWarning
{
//[super didReceiveMemoryWarning]; - calling this will unload the view
// Relinquish ownership any cached data, images, etc that aren't in use.
}
Related
My app utilises tableviews that all have associated UIImages.
I show my UIImages in the app using:
cell.foodImage.image = UIImage(named: foodImageArray[indexPath.row] + ".jpg")
I know in objective c something such as
UIImage initWithContentsOfFile
Could be used in order to keep the memory footprint low.
Is there something like this I can use in swift?
UIImage(named:) caches once loaded image and keeps it in run-time until app quits or 'out of memory' notification from system, on which cache somehow cleaned up automatically.
Thus it is better to use this constructor only for small images, which are either always visible in UI or used often.
For other cases (probably your table view case is here) it is better to use UIImage(contentsOfFile:) constructor with implemented some in-app cache logic to keep it for some workflow only but clean when go out it (other mode, scenario, etc. including force cleaning for 'out of memory' notifications)
There's a UIViewController method -(void)viewDidUnload. I tried putting NSLog("unloaded"); in there to see when the view is unloaded, but nothing was printed to the console.
Where do I put my code, so that before a view unloads I can perform an action?
If you read the viewDidUnload documentation, you see that it's related to low memory conditions and may be called to help with that. There is also a viewWillUnload that get's called before the view is released. It's also related to low memory.
If you're only interested in when the view is no longer seen, there are will/did disappear methods.
Are you using storyboard or not?
Have you tried any of this methods
-(void) viewWillUnload{}
or
-(void)viewWillDisappear:(BOOL)animated{}
If you are using storyboards the one that will that usually performs is viewWillDisappear.
A question about didReceiveMemoryWarning / viewDidUnload.
If my app has many view controllers, one of them is shown, and the others back (because of I use a navigation controller or tab bar controller, it does not matter), which view controllers will receive didReceiveMemoryWarning / viewDidUnload, all of them, only hidden, or only shown?
Is it possible that shown VC receives didReceiveMemoryWarning but not viewDidUnload (because as is shown, it doesn't make any sense).
By the way, I have these questions after seeing this diagram:
Thanks a lot for help.
First, there are two methods didReceiveMemwarnings:
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
is called when the application receives a memory warning from the system.
and UIViewController's
- (void)didReceiveMemoryWarning
Sent to the view controller when the application receives a memory warning.
Second, firstly is called the code in these methods(well, of course), then in those controllers which don't have superviews(i.e those which are not displayed at the moment) the view is deleted and viewDidUnload is sent
When a memory warning is received, it is received at application level, all your viewControllers and appdelegate receives it.
It is not necessary that viewDidUnload is called for any or all controllers. It is strictly dependent on how critical OS thinks that memory warning is. Like first time - your app receives a Level 1 warning then Level 2 and most likely at third time (in short interval) OS will terminate the application believing it has gone to unstable state.
I'm using a lot of small images that are placed into UIImageView objects. Currently, I'm trying to foresee the problems that might occur later, such as memory warnings, staying in background and etc. My app is quite small - less than 10Mb but still, I'm a little bit concerned. The reason is that I'm not sure how my app will cope with the situation when a lot of UIImageViews are loaded on screen, then app goes to background, and then after a long time comes back. Do I have to reload all on-screen UIImageViews?
I have read that iOS will cope with UIKit data (such as image views) itself when backgrounded. And that I do not need to worry about restoring this though. It would be OK if my UIImageView objects would use PNG image files directly from app directory. But the thing is I'm using spritesheets (files with several images packed inside), then pulling those images with CGImageCreateWithImageInRect, and then passing to UIImageView at some time point. Now, I'm questioning myself, will iOS cache my on-screen UIImageView objects, or do I have manually to reload those UIImageViews when app goes active? I understand that if a lot of apps will be running in background then my backgrounded app might be killed. But I'm worried about the situation when my app will be still alive (in background) but with released UIImageView objects...Please share you knowledge and insights :)
Current implementation of "background" apps do a complete snapshot of your app memory. Such approach guarantees that app will be restored after complete killing from a memory in unchanged state. This mean that you do not need to do any additional manipulations such as persisting of code-generated images etc to support restoring of the app. UIImageView will not be unloaded automagically if you will not implement a clean-up logic inside of applicationDidReceiveMemoryWarning for UIApplicationDelegate instance. However an auto clean-up logic implemented for cached UIImages loaded thru imageNamed method.
i've a navigation controller with several viewController and tableViewController.
I'm using all autorelease objects, the problem is that when i push a new view and i use it, memory from Instrumets increase of a bigger value of memory released when i come back in the navigationController. There's not leak warning, when i return to the view then, memory will not increase again, it's like if was all in cache.
I've tried also using objects own by me, with alloc....and release but the story is the same. Is it normal?
UIViewControllers (or to be exact, views/resources/xibs associated with them) are interesting since iOS will hold on to the resources in memory and unload them as required. This is why often the dealloc method will seem like it's never called. However don't worry, if you did proper memory management, your controllers and resources will be freed up as required - if there's a low memory warning sent to your app, all the views that are hidden or have been popped, will be unloaded and dealloc'ed.
Try testing your app again, just like you did before, but this time emulate low memory usage (can be done in simulator from the Hardware menu), then see if memory usage drops due to your controllers being freed up by the system