App is taking too much memory until a crash ! (iPhone) - memory

I am quite beginner in development and I'm making an application that have about 150 ViewControllers ! Each one have a UIImageView.
I've been doing a bit of testing, and after a use the app for a while on the iPhone itself, it Crashes when I keep viewing the ViewControllers.
I've been analyzing this in instruments, and I have no leaks, however my memory allocation just goes up and up and when I keep viewing the ViewControllers on my iPhone the usage just goes up and up until a crash.
I think it's clear that it's crashing because the app is simply taking up too much memory.
So could any one explain how to release viewControllers in order to free up the memory so there will be no crash
Thanks in advance !

The first question you need to ask yourself is why do you need 150 ViewControllers.
Do you want to present 150 different images?
If so, then multiple ViewControllers is not the way to go. You probably need to use a UIScrollView that will contain your images (not all of them at once, of course. Use lazy loading).
What's probably happening in your case is that you call "pushViewController" each time you need to display a new ViewController, but this doesn't release the previous ViewController. It simply stacks all of the previous ViewControllers and retains their pointers.
You see, the way Navigation Controllers work is that they have an array of view controllers. Every time you present a new view controller, it is added at the end of the array. When you click on "Back" or call "popViewController" the last item of the array is removed (and then released automatically from memory).
See this and this questions to learn how to create a UIScrollView to scroll images.

Related

Properly dismissing (or "destructing") views in Swift

I'm concerned about tiny lags and memory issues, and how they might scale.
My app is programmed using Swift and I've been doing everything in the app programmatically, including page navigation using presentViewController and dismissViewControllerAnimated.
Note: the app's page hierarchy can be several pages deep and each page contains quite a number of images.
I started experiencing tiny, occasional, lags which could appear more often on older phones; I can only test on iPhone 6 right now. I also noticed a small increase in memory while navigating through pages. Of course the memory level on the app (as observed in XCode) is not the same as opening the app in fresh state compared to going back to the first page after navigating through tens of pages, I'm expecting the memory level comparison could come at least close.
Now, my question: is there a proper way to "destruct" my page views (including UIKit elements, images, etc.) when such page view is dismissed?
I assume that by "page" you mean a viewController: There is no way to directly destroy objects with ARC (automatic reference counting), as they are deallocated automatically when their strong reference counter is zero. Since you experience unusual memory increase, it might be that you have some strong reference cycles in your code. Make sure to declare properties as weak wherever necessary. You should check out the ARC Guide for detailed explanation. I hope this helps.

Instruments viewcontroller segue not released?

I have a question about Storyboard, Segues and memory management. If I read about it on forums people say this is working properly but I was wondering the following, I made a small video to illustrate:
https://www.youtube.com/watch?v=ixs1Fiv5M9s
I grabbed a source from github explaining segues and unwinding them
I tested this in debugging and indeed I see all functions including dealloc is working
I run instruments and check how many times 2de view controller is created (every time #Persistent is increasing)
I check for changes in memory between the 2 states, and a lot is still in memory? But View controller is gone?
I am looking for the wrong data in instruments? I guess looking for memory leaks using modal and dismissing a view controller is not the right way to do this?
Can somebody explain me how to look for memory leaks? I need this for a much bigger app that is using a lot of segues, and sometimes this app crashes because of memory warnings...

Keeping UIViewControllers in memory

I am building an iOS app with one of those "hamburger menu" type drawers that open up to a list of options of the left. Like this:
Each time you click on an item, for example "settings" it loads a new viewcontroller and displays it on the main view controller. Now, the question I'm wondering is whether or not I should be releasing the viewcontrollers each time a new item in the menu is clicked.
For example:
You are viewing Inbox
You click Settings
I release InboxViewController and alloc init the SettingsViewController
I make the SettingsViewController the main viewcontroller
I'd like to keep all the viewcontrollers in memory, because I think it would provide for a more smooth transition from one to the next if it was previously allocated, instead of having to wait each time to allocate it.
I am using ARC
Is this bad practice? I might have 6-7 viewcontrollers in memory.
Looking at the SDK, Apple makes both choices: UINavigationController keeps the whole stack of VCs below the top, while UIPageViewController aggressively releases any page except the current one.
This is an example of a "speed/space" trade. Precomputing and caching objects will be faster (once running) but occupy more memory. Releasing more aggressively and building (or rebuilding) will incur some run time cost but occupy less memory.
The question might also be an example optimizing too soon, or unnecessarily. For a handful of typical VCs the allocations are quick and the memory footprints are (ought to be) small. Changing approach will likely have insignificant impact on either speed or space.
I'd start with whichever way is simpler (probably allowing VCs to be released passively is simpler) and see if there's a demonstrable problem that needs solving.
If you consider what you're doing, it's really no different than a UITabBarController. The views don't load until they are viewed the first time, but then are kept "alive" indefinitely. I would think as long as you keep the number of loaded view controllers reasonable (single digits) you'll probably be fine, with the one caveat that if they are all doing some intensive processing/loading/etc., it could become problematic.
I don't necessarily think keeping all the ViewControllers in memory is a good thing, unless the View contains objects that take a long time to fetch (i.e. opening a UIDocument or from a NSURLRequest).
Hope that helps!

iOS Tab Bar Controller memory management

I am using an iPhone storyboard, which main entry point is a Tab Bar Controller. This Tab Bar Controller segues to seven other different View Controllers. These View Controllers are mostly Table View Controllers or even Web Views.
I am not sure if I am searching for a problem, that actually does not exist, but my App uses ~80 MB Ram after all View Controllers have been opened once and therefore I have the impression, that this is wrong. The size does not exceed after calling the View Controllers multiple times, such that I don't think that I have memory leaks.
I have also searched for this issue, but the only thing, that I could find, was, that the OS caches all of the opened View Controllers and keeps them in the memory. Can someone confirm this? Will the Views be killed, if the OS doesn't have enough memory?
I have the impression, that I, as a good app citizen, should somehow release the memory of each and every View Controller after its viewDidDisappear? Or should I just leave the memory management to the OS?
WebViews usually crate caches that consumes at least 15MB. 80MB on simulator in my opinion is fine, if you open the same VC and after the first load the baseline is still the same, it's OK. You should only care that during memory pressure the system can easily get rid of the unnecessary memory.
TabbarVC keeps the VC instances because is supposed to do so.

iPad performance issues

I have this problem with performance of my iPad app..
For developing, I use MonoDevelop, which takes care of Garbage collecting. Still my questions are rather generic, I'd say.
OK, I use TabBarController with 5 NavigationControllers. Inside nav controllers there are some controllers, whose views are TableViews or ScrollViews. Next child is always just regular view.
I have a few questions:
1) TableViews never scroll smoothly. I have some alpha transparency, but since I did my graphics in Photoshop and not programmatically, this transparency should not cause much problems. It doesn't matter whether I have few or many results in table.
On the other hand, I have ScrollView which serves same purpose, i.e. to be a table with different layout and buttons have Photoshop generated transparency as well. It works perfectly.
For tables I applied DequeueReusableCell() which works fine (I see that memory usage is not increasing after scrolling). So why would tables scroll so jerky?
2) My app supports rotation. When I scroll table or scrollView and simultaneously tilt the device a bit, I get maybe 1 or 2 FPS. What is the best way to implement rotation? As I understand, ShouldAutorotateToInterfaceOrientation has to be overridden in all controllers in NavigationController chain. Also, I need to add observer in View I want some changes to happen. Do I have to use BeginGeneratingDeviceOrientationNotifications() in all views or is it enough to do it in Main.cs? Maybe this slows it down?
3) After some time app starts getting memory warnings and then crashes eventually. I tried to read logs and run app with Instruments, but can't find the cause of crash.
4) What exactly happens to a View popped from NavigationController stack? I can't reuse it. But could it be that Monotouch (or me) doesn't dispose it correctly?
I have almost same app for iPhone without support for rotation which never crashes. I think I'm doing something wrong with this rotation, but I'm not sure what.
Any help will be appreciated the most. So, thank you in advance.
Regards
1 - transparencies are always a problem. Even if you're not rendering the images in code, the phone still needs to do the compositing of the image, and that may take a lot of time. UITableViews have to calculate the final composite image every time a new cell is displayed, or the table is scrolled, while UIScrollViews can calculate only once, since the image won't change. So be very careful about it, turn the transparency off, and check if performance improves.
2 - You shouldn't need to notify every uiview in your application. Receive the notification in the controllers that you want to update only, like for example if you want to rearrange items in the UIViewControllers view.
3 - you have one (or many) memory leaks. My guess is that MonoTouch probably can't garbage collect UIViews or UIViewControllers, because they're still being linked from somewhere in UIKit, like a UINavigationController
4 - UIViews are not disposed by UIKit until the app gets a memory warning notification.
Like Eduardo said, alpha transparency in Views comes at a price. There are some tools that you can use to identify the bottlenecks discussed in these WWDC 2011 talks from:
https://developer.apple.com/videos/wwdc/2011/
iOS Performance and Power Optimization with Instruments
Understanding UIKit Rendering
In the "Debug" menu of the iOS simulator you can find various debugging tools that will color different regions of the screen indicating where some problematic rendering is taking place. The WWDC 2011 talks show what you can do to fix those problems.
For your memory problems, it is very likely that you have something pointing out to your objects around, so you need to make sure those objects are gone. While we currently are not shipping our new profiler for MonoTouch that can show the source of the problem, I wrote a "poor man's" debug utility that will help you narrow down which objects are alive. It is available here:
http://tirania.org/tmp/HttpDebug.cs
Call HttpDebug.Start () from your application and as you run, connect with a web browser to http://localhost:5000 to get a list of live Objective-C objects surfaced to C#. The tool is not perfect and shows a lot of irrelevant data, but it would at least give you an idea of what is going on.

Resources