UIimageView animation is using too much memory - ipad

I have two uiimageview animations. One on each of two view controllers in a navigation controller.
They have about 10-15 frames each. This is the smallest I can possibly make them.
They seem to be using a hell of a lot of memory though. Especially on startAnimating. Is there any way around this?
On my iPad this is causing a memory warning an a leak. I've tried looking into it, and as per an earlier question on here I've been using a lot of memory tools and such and narrowed the issue down to the startAnimating function.
I have read that this is because on startAnimating the imageView puts all the images into memory at this point.
However removing from superview and releasing dosen't seem to have a marked effect on the amount of memory reclaimed.
Is there any way around this? Bar creating a custom OpenGL style animation?
Thanks

Even i use to face same Problem.. I came up with solution by using custom navigation controller. Now i don't see any memory warnings or memory leaks.
Try to implement your own custom navigationController.

Related

iOS slow to release images while scrolling (no tableview)

Here is the problem :
I am writing an app which displays some pictures, with a treemap layout (for an example, see https://raw.github.com/beckchr/ithaka-treemap/master/Core-API.png)
This layout is displayed in a UIScrollView. Since many pictures can be added to that scrollview, I want to release the ones which are not on currently on screen. I am not using ARC.
At my point, I know which pictures I should release, and how to do it while scrolling (calling some "unload" method). There is no useless call of that method. The problem is that, when pictures are released, the scrolling stops for a little moment (a few ms, but this is enough to be bad looking, making the scroll kind of "jumping" and slow, not smooth at all).
What I've tried (put in the body of my "unload" method) :
imageview.image = nil
performSelectorInBackground:#selector(effectiveUnload) withObject:nil
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0,^(void){
dispatch_sync(dispatch_get_main_queue(), ^(void){
imageview.image=nil}
}
I think this problem is weird, since there is absolutly no slowing effect with memory allocation, but only with memory release.
Thanks for help, don't hesitate to ask for more information.
did you try removeFromSuperview to remove the imageview from scrollview
Don't add more and more UIImageViews - recycle them!
To save as much memory as possible you should follow the UITableView way of recycling views:
1. Once a view has left the visible area, add it to a "views pool" (and remove it from its superview. It's not an expansive operation!)
2. When a new view becomes visible, first check if there's a view in the pool. If not, then create a new view.
I know my answer doesn't answer your question directly, but that's the way to go. Otherwise you'll run out of memory eventually.

What's causing the delay in my segues?

One of my views freezes up for several seconds when I tap the back button.
In addition, when I tap on one of the items in this view, it shows a popup (custom, not a UIPopoverController). This popup appears quite fast, but when I "flip" the popup to see it's back side, the same long delay occurs.
I suspect the reason has something to do with the complexity of the view. As you can see in the screenshot below, it's a collection view, it has a background and some of the subviews are rotated (UIViewEdgeAntialiasing is on).
I used the Time Profiler in Instruments to figure out what's going on, but I'm stuck.
I don't see anything useful unless I deselect "Hide System Libraries":
If I look at the method names, I think they are related to auto layout. That suggests that it's trying to render something during the segue. But methods such as cellForItemAtIndexPath are not called.
There is also an iPhone version of this app where I don't experience this problem at all. It uses a tableview in stead of a collectionview. It also has a background and rotated pictures.
I took these measurements using the simulator; on my iPad Mini the situation is worse; it can take up to 20 seconds before the animation starts.
Update - Things I've tried thanks to your answers:
turn off UIViewEdgeAntialiasing : no effect on performance
I think this might be due to the UIViewEdgeAntialiasing flag. It seems that your main view (the one with lots of slightly rotated pictures) have lots of antialiased edges and hence is very taxing on the iPad's GPU. The fact that the drawing performance slows down when your popover is spinning (ie when the background is showing again) gives this some credence.
Try turning it off and see if the performance improves. How does it look like?
Rotation was the bad guy here. Each UICollectionViewCell has a UIView as a container view and within that is a UIImageView. I rotate it like this:
container.transform = CGAffineTransformMakeRotation(M_PI * someRandomFloat);
Remove that line and everything is snappy.
I use the same technique on the iPhone, but apparently this kind of rotation has less of a performance impact in UITableViewCell than in UICollectionViewCell.
I tried subclassing UICollectionViewFlowLayout to rotate cell itself in stead of one subview. Unfortunately that causes a similar performance issue.

View transitions slowed down on adding OpenGL view

Facing a really, really weird problem with an OpenGL View we are using in our app to perform some custom animations. As soon as the Open GL View is added into the project, all native View animations slow down. And by slow down I don't mean a drop in frame rate. The animations are stutter-free, except much much MUCH slower than normal (like someone enabled "Toggle Slow Animations" in the Simulator).
This is affecting only view transitions animations, for example:
a. transitionFromView
b. presentViewController (iOS6, or presentModalViewController on earlier)
While regular UIView Animations, CABasicAnimation etc proceed at the regular pace.
I haven't seen anything like this, and the results honestly have to be seen to be believed. :) But any idea what the problem could be (I'm not sure which piece of the code would help you debug, and I'm unfortunately not in a position to share screenshots or video)
It seems like the animation gets stuck while loading the OpenGL View, debug the
Lifecycle methods like loadView, viewWillLoad. The loadview, etc. happens within the
transition animation, maybe you can solve the slow animation by sending most of the loading
code in to a custom method which you call in viewdidload or viewdidappear.
It does not interrupt any other animation because thats a totally new action in the queue.
Hope this helps!
Found the solution accidentally several days later.
The problem turned out to be much sillier and unrelated. It so happens that if you have a UIView beginAnimation block that is not closed properly, future animations get all wonky. This faultily coded animation happened to be triggered at more or less the same time as the OpenGL view was being initialized, which led to my erroneous belief that the OpenGL View was at the root of this.
Thanks for the help!

iOS: Lazy-loading in UIScrollView with ARC

I'm working on an iPad-App with ARC which have to display thousands of UIImageViews in a UIScrollView...
When I load them all at once (or more accurately in a queue with GCD), I run out of memory after a while of loading..
Now, I thought i have to use lazy-loading and load only those UIImages which are necessary and a kind of release those which are no longer visible, but I don't know if this is possible with ARC..
Anybody have an idea to do this, or a better idea to handle this case..?
Thanks, tonistair
Make something that implements UIScrollViewDelegate, and in its viewDidScroll method, calculate the currently visible rect from contentOffset and bounds. Then remove things that are no longer visible, and add things that have just become visible (or some other appropriate algorithm). ARC has nothing to do with this.

A CATiledLayer-enabled UIView with drawRect-defined subviews crashes due to abnormal memory usage

We have an out-of-memory crash on the iPad 3 which we traced to the following scenario:
A UIView which uses a CATiledLayer and draws content (say, a PDF) has subviews with their own drawRect methods (which, for example, highlight search results). This makes Core Animation consume tons of memory (100+ MBs in the VM Tracker instrument), and can easily lead to a crash. While this issue exists on all devices, only on the iPad's Retina display does the cache size grow too large.
This can be reproduced with Apple's PhotoScroller example: subclass UIView, uncomment drawRect, and add an instance to the TilingView. The app will crash on iPad 3. Commenting drawRect resolves the memory usage.
Now, we can drop the subviews and do the drawing in the top-most UIView. However, working with subviews is convenient (since we're representing different, independent layers on top of the PDF). Two questions:
What is a good work-around? Preferably one that allows us to continue working with multiple views.
Why is this happening, exactly? I guess the cache mechanism is working overtime, but it would be great to understand the technical details behind it.
Thanks!
EDIT:
I want to elaborate on Kai's answer. The problem was indeed unrelated to CATiledLayer, but to the usage of UIViews that implemented drawRect.
In the case of PhotoScroller, I created a UIView which was of a size of the image - 2000x2000 and more, which creates a huge backing store if drawRect is present.
In the case of our app, the overlay views are full-screen (=~11 MBs on iPad 3) and we have about 5 of them per page. We keep up to three pages in memory while scrolling, and that means more than 150 MBs extra memory. Not fun.
So the solution is to optimize drawRect away, or use less such views. Back to the drawing board it is :-)
To 2.: Whenever you implement drawRect in a UIView subclass and have lots of instances of that class, your memory usage will grow dramatically. Reason is that a lot of optimization tricks in UIKit view/subview handling (e.g. when zooming or scrolling) don't work with such objects, because the framework doesn't know what you're doing/what you are drawing.
So - independent of retina or not - avoid implementing drawRect, especially when having many objects or many layers of subviews.
To 1.: I didn't exactly get what you are trying, but I implemented an PDF-Viewer which is also able to show additional content on top of the PDF. I did it all with normal UIView hierarchies, images etc. and I fear that's the only reliable work around you'll get
My experience:
Never add subviews to a UIView that's backed by a CATiledLayer
Never add sublayers to a CATiledLayer
Unfortunately, that seems to be the only practical answer - Apple's implementation goes horribly wrong in many different ways (not just performance - the rendering itself starts to exhibit visual artifact bugs, some of Apple's rendering code goes weird, etc).
In practice, I always do this:
UIView : view
+-- UIView w/ CATiledLayer : tiledLayerView
+-- UIview : subViewsView
...and safely add views and subviews to "subViewsView". Works fine.

Resources