iOS10. Swift. UIPageViewController memory leaks - ios

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?

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.

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

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.

UIDatePicker Memory Leak with ARC

I'm making an app that has a few view controllers with UIDatePicker controls.
After having lots of memory warnings, I've done a lot of debugging on the cause. Using instruments, I was able to see that whenever a view controller containing a UIDatePicker appeared, memory usage was going up by 2-3mb. Ultimately, this leads to a memory warning. While I can do so much in here, and have seen a dramatic decrease in crashes since re-writing these functions, I'm still not comfortable with this behaviour and want to fix it.
The UIDatePicker's are part of the XIB file. I've tried taking them out of the XIB and programmatically adding them. This doesn't solve the problem. I've also tried using a (thread-safe" singleton. This limits memory usage to only one instance (so memory usage doesn't increase), but I'm trying to avoid singletons wherever possible. Should I just suck it up and use a singleton?
I'm seeing this behaviour on iOS 5 and 4.3, across all devices that run it. I'm using ARC, as the title suggests.
Instruments does not show any memory leaks.
Here is a screenshot from Instruments. Each step up in usage is when a VC containing a date picker appears. The baseline at the start of the graph is 2.3mb of memory usage.
http://i.stack.imgur.com/1S7ns.png
Cheers!
The tool you want to use here is called heapshot. It will help you narrow down the types of objects that are being incorrectly held onto. As #sudo notes, the problem is probably in your delegate rather than the date picker itself. You're probably not "leaking" in the strictest sense of the term. You're probably just holding onto memory that you didn't mean to (which looks a lot like a leak).
You should take a careful look at whether you have any circular strong references. Do you have objects that have a strong reference to their delegate for instance? That will typically lead to a retain loop (which will never be released under ARC). Heapshot can help you find these objects.
I seem to have solved my own question. As this was an inputView, and I also had a UIToolbar with a "Done" button as the inputAccessoryView.
So now I create these programatically in viewWillAppear. In viewWillDisappear, I set the UITextField's inputView and inputAccessoryView to nil, and the date picker and date picker toolbar to nil.
They are no longer in the XIB file.This seems to work really well - memory spikes up by 3mb, then goes back down the second the views disappear. Now the app is running consistently at under 10mb of live memory - it spikes up to 15mb on occasion but very rarely.
Thanks for the help sudo rm -rf and Rob - heapshot analysis helped to try and get to the bottom of it.

UIWebView memory leak

I have an iPad app (IOS 4.3 & 5.0) that is creating a UIView with at least 2 subviews every time the user pages forward or backward. The 2 subviews are UIWebView objects.
On every relevant swipe the old UIWebViews are removed and deallocated properly (removeFromSuperview then stopLoading and set delegate to nil) and the parent UIView is deallocated. I can confirm that both parent UIView and the 2 child UIWebViews are absolutely gone.
I can see the retain count on the webviews as they are being removed and I am quite sure that they are indeed removed every time.
However my memory allocation continues to increase on every swipe by ~200-350k . No leaks in instrument but I can see the memory usage going up slowly.
On iPad 1 the app eventually (within 6-10 minutes of moderate usage) receives multiple memory warnings and is terminated. LowMemory crash log...etc is generated.
We use stringByEvaluatingJavaScriptFromString and loadRequest to populate the Webviews. Memory usage creeps up even when nothing is injected or loaded into the webViews.
Is anybody experiencing this kind of behavior with UIWebViews ? Has anyone dealt with this successfully ?
Thoughs, comments & answers would be greatly appreciated.
Try to use Instruments but with the "Allocations" template and watch the "# Living" columns for UIWebView. I usually use it like this:
Profile app with Allocations template
"Warn up" the app by going thru all tabs, scroll around etc.
Press "Mark Heap", this will create a "Baseline" heapshot
Do the thing you think causes objects to stay around
Press "Mark Heap" again, this will create a "Heapshop #" heapshot
Inspect the objects in "Heapshop #" which will show size and number of objects created and alive since the last heapshot.
Goto 4
Not aware of any leak, but if you are destroying and re-creating the same view hierarchy every swipe, why not store the views and re-use them instead?
Regardless of whether they leak, webviews are computationally expensive to set up, so re-using them and just reloading the content should give you a performance boost, and may solve your leak as well.
are you still seeing this issue? I traced something which looks like unbounded memory usage (not necessarily a leak, but I get low memory warnings and eventual process termination) by calling stringByEvaluatingJavaScriptFromString over and over:
[webview stringByEvaluatingJavaScriptFromString:#"something()"];
It seems like there is something odd there.

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