Size of memory usage of IOS App - ios

I have created an app with 12 view controllers and its got a lot of graphics ( image files )
When I launch the app, I notice the memory goes up as I move through the view controllers.. once I have moved through all the controllers the memory is 530Mb
so my questions are :-
a) is this a lot of memory to be using
b) should I be worried
c) how can I remove view controllers from memory as I navigate round.. for example I have a view controller for on boarding , but once some clicks on skip or get started, I segue to the next view controller, so in theory it doesn't need to be loaded any more..
Thoughts ?
Im running on an iPhone 7 Plus which has 3Gbm, but want to be able to run the app on other phone models from iPhone SE onwards. however I notice the memory profile is about 50% no the iPhone SE but assume thats because its not loading the x3 images as per plus phone

a) is this a lot of memory to be using
lot is a relative term and whether 530Mb is lot or not completely depends on what app is doing and what kind of app it is! If its a game with rich graphics I wouldn't be bothered much but if its a plain utility app I would be concerned!
b) should I be worried
Memory getting accumulated/increasing as user loads various screens of app is a very common scenario. You should be bothered if it keeps increasing and never comes down. Every time a VC loads it might load, heavy graphics with it or might allocate large amount of variables and consume lots of memory to perform its function. Which is quite fair. But once user pops the VC from applications navigation stack all the memory allocated by the VC should be returned and total memory consumed by the app should come down. Ideal memory foot print would look like a wave where it reaches peak and comes down once VC pops out. If thats not happening you are in trouble :)
c) how can I remove view controllers from memory as I navigate round
Use proper navigation techniques. Don't keep pushing the VC's to navigation controller stack unless you actually need that VC instance to be retained in memory. All VC's pushed to Navigation stack will continue to be kept in the memory till either user kills the app or iOS decides to kill the app on receiving memory warnings.
Write deinit/dealloc in each VC and make sure it gets called every time user pops the VC by either tapping back button if its pushed or by dismissing VC if its presented modally. Ensuring each VC's deinit gets called is the best way to ensure VC does not hold up any unnecessary memory.
Make sure none of your VC has code which results in retain cycle and retains the objects in memory forever. Example : If your VC declares a block and holds the strong reference to block and if you pass self to block your block and self will never be released. Classic example of retain cycle. Make sure your code does not create such dead locks
Never hold anything strongly by using either strong/retain unless its necessary.
Use instrument to find the memory leaks and reference counts of each objects just to make sure there is no memory leaks in ur app.

Related

Memory management in IOS7 and "Terminated due to Memory Pressure"

The reason why I am doing everything below: I have a GPS tracking application which should run in background all day long. Memory usage doesn't go down when I put application in background. It seems like views are not removed from memory when app goes into the background... That is why the app is closed in few hours of normal usage of iPhone ... From IOS6 experience - memory usage should drop to cca 8KB.
Then I tried to debug/isolate the problem ...
I created simple ViewController with UIMapKitView just to make sure that view is consuming a lot of RAM (e.g.: 12-17MB). When app goes to background app uses same amount of RAM until "Terminated due to Memory Pressure" message. Still - sometimes memory lowers to 4KB and everything is OK. Problem is because it works kind of "random" and the app is plain simple.
Can I manually release RAM which is consumed by views? E.g.: set self.view = nil? Should I do it?
I also noticed that "- (void)didReceiveMemoryWarning" is not always called before app is killed. I would expect that when OS needs more memory it would first release views, than ask me to clear anything I can via this method ... Isn't this a little bit strange?
Apple redesigned the way a VC's (view controller's) views were loaded quite a while back - I want to say starting with iOS 5? iOS 6? It used to be that the system would unload your VC's views when a VC was not front-most and it needed the memory.
With the changes, a VC's views are NEVER unloaded while the VC is active. ViewDidLoad only gets called once in the lifetime of the VC, and viewDidUnload is no longer called at all.
I don't know what would happen if you set your (non-frontmost) VCs' content views to view manually. Would the system load your view hierarchy when that view became frontmost again? You'd have to try it, but it is risky since I don't think the OS is designed that way any more.
If your VCs views are holding significant amounts of memory, you might want to re-architect your app so only the front-most app is kept around, and the other VCs are released (after saving their state.)
Apple does not make this sort of app easy to write. To the contrary, they actively discourage it. The GPS is a huge power drain, so keeping it active constantly is going to drain the user's battery fast.
I remember hearing about a new location chip in the 5s that will record a "crumb trail" of location data for your app even when it's not running, at your request. You might look into that, although it would only work on the newest devices with the A7 chip and location chip.
In my case the problem was specific IOS7 version. Every app was crashing with this version of OS. When we updated OS version, everything started working back as it should.

Strategies for "realistically" testing low memory conditions in iOS Simulator

I'm at a point in the development of my little app where I'm implementing didReceiveMemoryWarning and such, but I feel like I don't have a good grasp on the best way to test what I'm implementing.
First off, apparently in the simulator, didReceiveMemoryWarning isn't triggered for apps that aren't in the foreground until that app is brought back into the foreground, according to this question - actually, that matches my own experience, but I was prone to ignore it because it doesn't really make sense. (Why would I want to delay clearing up my memory until I'm coming back into the foreground and probably about to need that data again?) Does this match the behavior of actual hardware? If so, does it make sense to cleanup tasks in applicationWillEnterBackground in addition to didReceiveMemoryWarning?
Second, generally, what is a good strategy for triggering the "Simulate Memory Warning" menu item in the simulator in such a way as to trigger memory warnings in a manner that they're likely to happen on the actual hardware?
Q1: Does this match the behavior of actual hardware?
A: Yes, the simulator and the actual device behave the same in this regard (e.g. if your app is suspended and is not running a background task, it does not receive applicationDidReceiveMemoryWarning).
Q2: Does it make sense to cleanup tasks in applicationWillEnterBackground?
A1: Only insofar as that your app must prepare itself for a complete restart. If your app remains suspended and the user does a lot of things with other apps, your app may become fully unloaded - even though the app may still be visible in the task switcher, when the user activates it the next time, your app delegate will receive application:didFinishLaunchingWithOptions: (not applicationWillEnterForeground:).
A2: I wouldn't bother with cleaning up memory, but you should make sure that by the time applicationWillEnterBackground has finished, any user preferences and other stuff are saved so that the app knows where to take up again when it is activated the next time.
Q3: What is a good strategy for triggering the "Simulate Memory Warning" menu item?
A1: I doubt whether a general strategy can be formulated since every app is different.
A2: To use a specific case: In my app, I don't use the app delegate's applicationDidReceiveMemoryWarning to relieve memory pressure, instead I rely on the fact that when a memory warning is sent, iOS also invokes viewDidUnload on certain view controllers that are not in use. Therefore I generally use the memory warning simulation to test whether my view controllers' viewDidLoad and viewDidUnload are balanced correctly.
A3: Concrete example: My app uses tabs, so a favorite scenario of mine is to 1) display the tab with the view controller (VC) under test; 2) navigate to a different tab; 3) simulate the memory warning (iOS invokes viewDidUnload in the VC under test); 4) navigate back the original tab (iOS invokes viewDidLoad in the VC under test).
A4: If you want to use a similar approach, then you have to figure out for your app which views might be unloaded by iOS. In my (limited) experience these tend to be views that are unrelated, such as views on different tabs.
Here's my answer to your second question - it also kind of answers your first question:
I've used the "Simulate Memory Warning" feature to effectively reproduce issues where a child view controller consumes enough memory such that its parent must free up resources.
For example, consider a child view controller that displays the camera/photo library (i.e., UIImagePickerController)). This uses a significant amount of memory. If the picker controller consumes more memory than is available, the parent's view controller will be unloaded, and once the parent view controller is shown again (when the child is popped), the parent's viewDidLoad will be called again. This means that any variables set in viewDidLoad will be set again, potentially with memory leaks or bad pointers.
The "Simulate Memory Warning" helps to find these problems. You can go into the child view controller, select "Simulate Memory Warning", then pop the view controller and check for problems.
Note that the "didReceiveMemoryWarning" is more relevant (imho) to let you know it happened than actually trying to release memory at that point.

Main View gets dark when coming back from Background

I am using RouteMe's library and services to display maps.
The main ViewController holds an *RMMapView that inherits from UIView. Basically it just fills up with tiles.
When my app goes to background, and after a while, after other apps are loaded into memory usually, comes back to foreground, The main mapView goes completely black and I can't see anything except for my UI.
(I guess due to lack of memory)
How can I prevent that from happening ?
Thanks!
you cant prevent a Memory warning from happening, however if you are 100% sure that you cant handle the memory warning in some view controller and to stop the call to viewDidUnload remove the implementation of didReceiveMemoryWarning in your view controller
Please note that disabling the viewDidUnload is not recommended, you should reflect about your memory usage and present a better memory management technique

Monotouch memory view controller problems

I have a problem with the memory consumption of my app I hope you can help me with this, I have a Navigation Controller with maybe 10 controllers to navigate forward or backward, I'm using Instruments to check for the memory allocations (also used the mtouch profiler), when I navigate forward (1st time) obviously the memory consumed by the app increases .. but when i click on the standard back button of the nav controller the memory stills being the same amount and worst of all if I go forward again the memory increases more (i.e.: homeVC 10mb, VC1 = 10.5mb, back to homeVC = 10.5 mb, forward to VC1 = 11mb), yes the memory is increasing while I still navigating through the VCs. In this scenario I have the following questions:
What is the behavior of the app on the standard Back button of the nav controller (it executes a PopViewControllerAnimated?).
PopViewControllerAnimated and the other Pop methods of the navController should release the memory consumed by the dissapearing VC?
If the Pop methods of the navcontrollers don't release the memory of the app, when I should dispose my disappearing VCs to avoid consuming so much memory? (I want to know the best work of manage the memory in the mono touch apps, maybe use the DidReceiveMemoryWarning method? or there are another places when i can manage the release of the memory of my app).
Thanks in advance for all your help.
This sounds suspiciously similar to this bug: https://bugzilla.xamarin.com/show_bug.cgi?id=1889
You can work around it by fetching the ViewControllers property of the navigation controller once in a while.
Can you post the code you use when you allocate and push your VC?
What I'm guessing is happening is you aren't releasing it after you allocate it, so when the NavigationController releases it when you press the Back button the retain count is still +1.

Memory warnings in IPAD app with UITabbar of 8viewControllers

My application which is a UITabbar app has eight tabs. one tab for playing Audio, one for Playing Videos, one for Books(Leavesview is used for opening jpg image pages),one for Gallery.....so on.
So, Once I open all tabs the app throws memory warnings and crashes.
Then I did this: In each tabs viewController, I have allocated everything(views, imageViews.....) in ViewDidAppear method then I did removeFromSuperView and release in ViewDidDisappear method.Even then the problem persists.
Using Activity Monitor I observed that the app crashes when it exceeds 128 MB of Memory.
Each tab's ViewController is Occupying around 40MB memory. Even though I release everything in the ViewDidDisapper of the tab the memory is not freed but kept on increasing.
Is there anything regarding memory I have missed. Please Help me resolve this , Thank You.
I have noticed that when instantiating a UITabBarController it loads all it's dependencies and is really stubborn when trying to release an entire UIViewController. I've done a few things to combat this when I've had high memory UIViewControllers attached to a UITabBarController. What I suggest is only releasing the memory hog controls associated with each UIViewController on the ViewWillDisappear and re-Instantiating them on the ViewWillAppear rather than trying to release the entire UIViewController. Typically this is bad practice because you want to recycle as many of the controls as possible but if you have to stick with the UITabBarController this is the only way I've been successful.
If I misread your post and you aren't trying to release the UIViewController the I would need to see some code to figure out why things aren' releasing on ViewWillDisappear.

Resources