> On 8 May 2015, at 2:43 pm, Michael David Crawford <mdcrawf...@gmail.com> 
> wrote:
> 
> My iOS app enables the user to toggle on and off a square grid.  When
> the grid is enabled, a tap inside a cell toggles the color of the cell
> between black and blue.  When the grid is disabled, one can use a
> pinch-zoom gesture to adjust the sizes of the cells.
> 
> (I'm not so sure that's a sensible UI but that's not the problem I'm
> looking into just now.)
> 
> If the pitch of the gride is fine, then there are many lines on the
> screen.  If I autorotate, redrawing the vertical lines takes hundreds
> of times as long as redrawing the horizontal lines.  That makes sense
> as one can draw a horizontal line by incrementing a pointer into the
> image buffer.  To draw a vertical line one has to draw a pixel, then
> calculate the memory address of the next pixel vertically downwards.
> 
> I wonder if there is a better way to do this?  I'm using UIRectFill to
> draw 1.0 point thick rectangles.  I thought of using CoreGraphics
> directly but Instruments tells me that all the time is spent way down
> in the innards of CG.
> 
> Before I draw the grid, I erase the whole view to blue, then draw
> black rectangles for my cells.  A small optimization is that if two or
> more cells are horizontal neighbors, I draw them in one UIRectFill
> operation.
> 
> The vertical line drawing is so slow that it is disruptive to the user
> when autorotating - the whole UI freezes for as long as two seconds,
> looks distorted during that time then very quickly renders the desired
> appearance.
> 
> One way would be to render a single vertical line into a tall, narrow
> offscreen image buffer then copy that buffer into multiple locations
> on the screen.
> 
> Another way would be for me to render the entire view in an offscreen
> image buffer, which I expect I could do far more efficiently than by
> making many calls into UIRectFill or even CoreGraphics.
> 
> I've done lots of direct memory pixel manipulations over the years,
> that wouldn't be a problem for me to implement but before I do, do you
> think it would be a good idea?

Not until you exhaust simpler options.

Drawing a lot of rects is definitely going to be inefficient compared with 
drawing lines. Consider a 100 x 100 cell grid - that’s 10,000 rectangles but 
only 200 lines.

When I’ve drawn grids I’ve always done it by drawing lines across the whole 
visible width or height, and I’ve not run into major performance issues. That 
said, I haven’t done it on iOS, only on Mac where there’s a lot more 
performance in hand. One way I’ve done it which would work on iOS too is to 
draw lines into a CALayer then tile that layer repeatedly - not once per cell 
but once per n cells, where n is something useful, 100 say. That way you incur 
the line drawing time once but the layer is cached and is simply copied when 
drawn multiple times (not disimilar to your image idea but likely to be a lot 
faster as layers are highly optimised for performance and you’re drawing the 
original tile in a fast way).

That still leaves you with filling in some of the cells. Depending on how many 
that could be, you might not win - worst case would be a chequer pattern where 
no cells share a neighbour in common. But if you only colour a few cells on the 
grid, just draw the grid using lines and deal with the filled rects as a 
separate step.

Also, never draw what you don’t have to - only draw what’s visible. As you zoom 
in, that should eliminate huge numbers of unneeded rects.

I bet you can get a lot more performance out of Core Graphics yet.

—Graham



_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to