I have a very image heavy app. (And before you say: no I can't reduce the amount of images). This means that there are a lot of UIImageViews going on in my storyboard files.
The overall structure of the app is something like this:
The Content View Controller is the one that is image heavy and at any one time up to around 12 of them can be in memory at any one time due to the page view controller.
I have been getting memory warnings and leaks (from my investigations these are separate unrelated events) and the system has terminated the app on occasion.
Aside from writing my own implementation of UIPageViewController what can I do to reduce memory footprint?
I don't think you need to create you own implementation of UIPageViewController, you just need to use UIPageViewControllerDelegate/DataSource and UIViewController wisely.
For instance UIViewController has a method that is triggered during memory warnings, are you getting rid of heavy images on VCs that are not visible inside that method?
Related
I have implemented CustomPageViewController which is subclass of UIPageViewController.
It has array of created ViewControllers
While running my app, I noticed that on every swipe(transition from one page to another) memory used by application increases, and memory usage is a non decreasing function of number of performed transitions from one page to the other.
While debugging, in order to solve this issue, I added deinit method and print statement to ViewDidLoad & deinit - ViewDidLoad is called once, and deist isn't called at all while swiping.
In order to make sure that this behavior isn't because of a source leakage in my CustomViewControllers I added ViewControllers with some buttons instead my custom classes, but memory leaks remained.
I have noticed a lot of questions on SO, with the same issue, for iOS versions since 8, most of them relates to objC, and in the rest no solution is given.
Do you use UIPageViewController? If so have you ever noticed that it leaks memory? As functionality it provides: to swipe among set of views is of high demand, how you implement that? Did you implement your own version, or fixed existing?
I am going in and out of UIViewControllers.
Every time I am going in memory increases, but when I am getting out (pressing Back) memory is not decreasing.
I have weak #IBOutlets, vars and lets.
How can I fix it?
p.s. One of the #IBOutlet is container pointing to another UIViewController
Ignore the comments suggesting retain/release breakpoints and peppering your code with log calls; that's an unwieldy tactic that misses entire classes of problems. Abizern's suggestion to use Instruments is a lot more spot-on. Run the Leaks instrument to look for leaked instances. Browse the other memory instruments as well. Instruments is a &#&$&-ing magical debugging tool and so many developers ignore it for reasons I can't fathom. Spend a few minutes with a tutorial and you'll save months of debugging time over your career.
It sounds like you are creating a new UIViewController every time you switch between views. Try to create the segue to be an unwind segue, this will remove the current view from the stack. Otherwise it appears that you are just continually adding to the stack of views. Tell me if this works.
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.
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!
I am new to IOS and coming from pcs I am trying to get a feel for managing memory and battery resources.
I have a UIImageView subclass which is is very light (it's an image placeholder with a handful of methods). This subClass is repeatedly added to, and removed from, several root views. I hold an IBOutlet reference to the subClass on each root view.
Would you:
Simply add/remove the subClass from the root view (and keep it in memory)?
Or
Create and destroy the subClass instance each time (freeing the memory but extra work)?
Is this worth considering or am I worrying over nothing?
Would your answer be the same if the UIImageView subClass was very large?
Is there a way of measuring these matters?
In general, you can use UIImageView with disregard on iOS. UIImageView is not much more than a clipping region with some methods for dealing with images.
The resource which takes up more memory is the UIImage contained by the UIImageView and these are cached by iOS.
So there is little cost to creating UIImageViews and destroying them, just take care that you dealloc them and don't leak memory and you should be fine unless you have hundreds of them.
The subclass being "large" doesnt matter, the code in a class is never loaded more than once. If the class has alot of extra state - that will take up some memory but I cant image a whole lot of that in a UIImageView.
You better just keep it in memory. User experience will be much better if you don't slow down the device by continuously recreating the image view. One single poor UIImageView instance is not memory heavy enough to worth the time and effort to recreaty all the time.
Keeping it an memory to improve performance isn't as much of a hit as you would think - taken from the other answers you have. But you should remove it from memory if you get a memory warning, and provide a way to bring it back to life as needed.
I would go with your first option, keeping it in memory. This is just because I think it is handy to keep my views alive and reuse them. This means that they will remember their state and content and that helps out in many cases. I usually write methods to reset the content or refresh it when needed.
Keeping it in memory might also increase the loading of the view slightly, but usually you do not notice the difference, and I see people using both ways.
And yes, I would say you are worrying a bit too much, especially if you think this decision would affect battery.
Regarding memory management, keeping the imageview in memory or releasing/recreating consumes the exact same amount of memory as long as you only have one imageview that you are using. The only difference is that you are allocating and releasing it repeatedly if you are recreating it.
You could however get memory issues if you start creating new imageviews every time the user opens them and never letting go of them, but that means you are doing something fundamentally wrong in your programming.
As long as you know what you are doing, no need to worry about the amount of memory in a case like this - there's plenty. Start worrying if you are handling large images.
Especially if you use ARC there is not much to worry about, just start hacking away. If you are managing memory manually, I do recommend trying to reuse stuff because that causes less headache and risk of giant leaking. Use leaktools and analyze tool to make sure in this case.