Subclassing UIScrollView for drawing w/o views - iphone

I'm contemplating subclassing UIScrollView (the way UITextView does) to draw a fairly large amount of text (formatted in ways that NSTextView can't).
So far the view won't actually scroll. I'm setting contentSize, and when I drag, I see the scroll indicator. But nothing changes (and I don't get a drawRect: message).
An alternate approach is to use a child view, and I've done this. The view can be over 5000 pixels high, however, and I'm a bit concerned about performance on an actual device.
(The other approach, be like UITableView, would be a huge pain -- I'm "porting" Mac Cocoa code, and a collection of views would be a huge architecture change.)
I've done some searching, but haven't found anyone who is using UIScrollView to do the drawing. Has anyone done this and know of any pitfalls?

All that UIScrollView does when the user scrolls is update its bounds rectangle, which causes the scroll views subviews to move. You could try setting the scroll view's contentMode to UIViewContentModeRedraw. From the docs:
UIViewContentModeRedraw
Redisplays the view when the bounds change by invoking the setNeedsDisplay method.

Related

Using drawRect stretches during orientation change

I have a tableView. Instead of having multiple subviews in each tableViewCell , i have added one main subview which draws each of the other subviews in its drawRect method.
(I have read somewhere that this makes scroll animation look better. Also apple has a sample project CustomTableViewCell).
First , problem is when i changes the orientation of device, then drawRect does not call automatically. And each tableviewcell appears to be stretced.
I solved this by using
mainView.contentMode = UIViewContentModeRedraw
This solves the problem. Now when the orientation change is done, drawRect is called automatically .
But during the orientation change, the animation of rotating view still shows each tableview cell stretched. It is a very small thing, but still it is noticeable. Can anyone suggest something on this ?????
You can't redraw during animation (not easily, anyway).
Split the table cell into components again and setup autoresizing correctly. The animation will then animate only component positions and it will look fine.
Where did you read drawRect: would make scroll animation better? Did you have some problems with scrolling animation?
Edit:
IMHO There is no way how to fix resizing animations and keep the performance increase from using drawRect: instead of subviews.

Adding views on top of UIScrollView

When you add a subView to UIScrollView, should this change the smoothness, or anything else for the UIScrollView? For example, if you have a UIScrollView with mainly text, then add a couple of views on top of it in order to add an effect to the text, should this change any of the gestures, or smoothness of the original UIScrollView without the subViews? Thanks.
It won't change the gestures.
As for the smoothness, it depends on how heavy your subviews are. I guess that if you add a lot of them, and they require to render a lot of dynamic content and such, it could make the scrolling a little rough, but if you are adding only a few subviews you should be fine.
As a comparison, think that a UITableView is a UIScrollView with a LOT of subviews on it (each cell is a subview, and cells have several subviews too), and it usually renders fast.
If the sub views you implement have the worst drawRect: implementation in the world, you don't need very many views to get slow, un-smooth scrolling.
You should profile your code in Instruments with the Time Profiler, and see what causes the slow scrolling.

UIScrollView performance problem because of lots of labels

I've got a pretty big UIScrollView (contentSize 8000 x 960) with a lot of small labels.
The labels are only added if you scroll to the area where the label belongs to. So, at first, the scrooling is smooth, but as more and more labels are loaded, the performance suffers more and more.
What's the best solution to keep the scrolling smooth? Is CATiledLayer the way to go? Or should the labels off the view should be hidden or something like that?
Thanks a lot for your help!
Stefan
EDIT:
I got a huge performance boost when drawing some objects instead of using views; but now, I've got another problem; if I draw directly onto the UIScrollView, everything performs great. But if I lay a UIView on the UIScrollView and draw on that, performance goes down again (both times calling setNeedsDisplayInRect: in scrollViewDidScroll:).
So hierarchy:
UIWindow
UIView
UIScrollView <== drawing here
works fine.
But hierarchy:
UIWindow
UIView
UIScrollView (size 8000x960)
UIView (size 8000 x 960) <== drawing here
performs bad.
Any ideas why? I need the UIView above because the drawing should be ABOVE some UIViews; so I place the UIViews in the scrollView and draw in the view above...
The label reuse is one of possible solutions. Sometimes it doesn't help a lot. When a new UIView appears the drawRect method will be called and that may cause problems with animation.
Sometimes the best solution is to draw your labels (I mean text) directly using Core Graphics without creating UILabel object or something else. The CALayer will increase performance, but there is a possibility that it will not help you a lot.
But first of all you should remember that views with alpha = 0 or hidden = YES will not be drawn at all, so there is no penalty for using them. Maybe you should try to hide unused ones before using Core Graphics.
The best way would be to have just a few UILabels and reuse them. But you'll have to implement - (void)scrollViewDidScroll:(UIScrollView *)scrollView and do some reusable logic there. Depending on case it might be easier to use a UITableView and transform it 90 degrees, so it looks like a scrollview. That way you can the build-in reusable logic of the TableView.
For others seeing this post, I was able to drastically improve performance and keep UIViews in a scroller without using a table by enabling each view's "shouldRasterize" property. This property renders the view as an image while the view is in motion, causing it to not need to be reprocess for each pixel it moves. So, if I have a UIButton called button, it gets enabled like this:
button.layer.shouldRasterize = YES;
Did u try something similar to UITableViewCell
dequeueReusableCellWithIdentifier
Using a reuseIdentifer to reuse the once allocated labels..

Is Core Animation causing my subviews to call -drawRect for every single frame?

I made a nice UIView subclass which paints all its stuff in -drawRect:, because people said that's good. That view is a subview of another. This another view is beeing animated with Core Animation: It's scaled down, rotated and moved. However, I encountered this: -drawRect seems to get called trillion of times during animation, and performance sucks.
Is that normal or did I do something wrong, probably?
And I have found this in the documentation of UITableViewCell, which is strange:
However, drawing in editing mode is
not encouraged because, as you might
recall, custom drawing while cells
animate into and out of editing mode
severely affects performance.
So -drawRect: is very very bad when doing any core animation thing? I also remember from some other apple resource, that they "don't redraw during animation". Paradoxon. Again.
If your UIView's contentMode is set to UIViewContentModeRedraw then, according to the documentation setNeedsDisplay will be called whenever the bounds change. I'm not sure if this would be true during animation, however (I was under the impression the animation system behaved differently) but could explain the flurry of calls to drawRect.
drawRect: should only be called after setNeedsDisplay: YES is called on your view. I'm guessing that as the scaling is happening your view is being asked to redraw. If the scaling, rotating, and moving is part of a transition you may be able to perform the transition on a cached view.

uiview Transition problem

i have a UIview holding two other UIviews. that two subviews having 15 buttons and images. i have to translate the parent view. but the translation is not smooth in 3g phone. im using UIviewanimation and CGAffineTransformTranslate for translating the view. please help me for making it more smoother.
This is a though question to answer in a general way. I have had views that scrolled smoothly suddenly animating jerkily after just a small change. In short, you need to make sure to have as few subviews as possible and have as few non-opaque views as possible (pngs with alpha values translates to non-opaque UIImageViews).
If all else fails, you can render the whole view into an image, switch out the view for the image just before scrolling, and then re-insert the view again after the animation. That way, you are only moving one big and (hopefully) opaque view.
If you have many images make sure they are small-sized, otherwise theyd take up too much memory and there would be nothing to do. To my experience 4-5 large images(740-480) were too much for the phone to handle.