0
votes

I'm making simple number coloring game (like sandbox, pixel art, unicorn, etc) and came across a problem. I tried various methods of filling rects in the screen.

  1. At first i created a backgroundView(a simple UIView) which had 2500 subviews(also UIViews), each one had size = (CGSize){50,50}. Added a tap gesture recognizer, detected which view should be filled, and simply changed the background color of that view. But when i placed the backgroundView in the scrollView, the scroll and zooming were awful.

  2. Tried same thing but this time each rectangle was a CALayer. So a backgroundView, which had 2500 sublayers(each was a CALayer with 50,50 size) - zoom and scroll was also awful.

  3. Tired to use custom drawing with overriding drawRect method in UIView subclass or drawInContext in CALayer subclass(i was filling rects with CGContext), this time problem was also caused by the zooming and scrolling. Because i needed to update every rect when user zooms, it was triggering a lot of drawRect calls, and performance was also bad.

Any thoughts how can i fill rects in the screen ?

1
We can't help you fix your code if you don't provide it.Adam Kaplan

1 Answers

0
votes

Explanation

Yup! Adding 2,500 tiny UIViews to a scroll view can destroy performance. I wouldn't use that approach, but if you do, at least make sure that subview_N.opaque = YES; on all subviews to disable compositing.

The CALayer approach that you described is basically the same as the UIView approach because views are backed by CoreAnimation layers (see -[UIView layer]).

The best options for drawing thousands of rectangles to the screen on iOS without decimating frame rate, is to use one of the following approaches:

  1. Draw directly using CoreGraphics
  2. Draw directly using OpenGL (extremely involved)
  3. Use a layout engine such as UICollectionViewLayout

Now, you said you had tried overriding -[UIView drawRect:], but you didn't provide any example code for us to checkout. Please update your question with actual code for method #3 if you want more specific feedback. It's very likely that something is wrong with the drawRect code you created. CoreGraphics can definitely draw thousands of squares on screen without dragging frame rate down that badly.

One Solution

I recently released a project, YMTreeMap, that draws thousands of rectangles into a UIView to create financial TreeMaps. It's in Swift, not Objective-C, but the underlying concepts are the same. For this, I created a custom UICollectionViewLayout that lets Apple's well tested UICollectionView class handle the nitty gritty of selective drawing, zooming and animation.

The example UIViewController code in the YMTreeMap project shows how to draw thousands of colored rectangles to the screen if all you know is their location and size. This sounds like what you are doing. Since you're also scrolling and zooming, this solution might be perfect for you because UICollectionView has native support for both of those.