5
votes

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...

4
Did you try removing labels which are not currently visible? Your use case is solved by UITableView, by the way. Not sure how you'd like your labels to be displayed though.Alexei Sholik
I just did now; didn't seem to help :( Isn't the overhead with looping over hundreds of views and determining if the view should be visible killing the performance gain?swalkner
That's true, enumerating over all the labels during each scrolling event is not a good idea. You should find a bottleneck first. What's the Time Profiler instrument saying? Is it pointing to your code as being the hungriest one?Alexei Sholik
it even seems as if it isn't necessary to hide the objects myself; if I scroll to a pretty empty area, the scrolling is smooth again... can it be that iOS handles this by itself?swalkner
Well, yeah, that definitely can be the case. I'm not sure I understand the problem. Performance suffers when you scroll to an area with many labels in it? Could you show a screenshot of what you are trying to achieve? Using lots of labels may not be the best solution.Alexei Sholik

4 Answers

1
votes

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.

1
votes

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.

-1
votes

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;
-2
votes

Did u try something similar to UITableViewCell

dequeueReusableCellWithIdentifier

Using a reuseIdentifer to reuse the once allocated labels..