1
votes

Since I have to draw many points in a UIview, I'd like to display an activity indicator view over the UIView.

I tried something like this, but it doesn't work.

-(void) drawRect:(CGRect)rect
{
     [self.activityIndicatorView startAnimating];

     CGContextRef cr = UIGraphicsGetCurrentContext();
     // Lots of CG functions (take a few seconds)

     [self.activityIndicatorView startAnimating];
}

What can I do to show a spinning wheel while drawing?


Edit with a solution (thanks @dasblinkenlight):

Two UIImageViews, one to be used as a placeholder (where the UIActivityIndicatorView runs), and another one that draws the CG content, named Renderer.

As read here the Renderer class writes a UIImage. Placing the drawrect call in another queue (background) when it finishes the placeholder can use the image to be displayed.

That's the code:

dispatch_queue_t myQueue = dispatch_queue_create("MyQueue", 0);

dispatch_async(myQueue, ^{
    [self.renderer drawRect:self.placeholder.bounds];

    dispatch_async(dispatch_get_main_queue(), ^{
        [self.placeholder setImage:[self.renderer renderedImage]];
    });
});

I stil can't understand why I have to call directly the drawRect function, instead of the setNeedDisplay. Is maybe because it is running in background?

1
You could draw into an image in a background thread and then just draw the image onto the view when done... Or you can use CATiledLayer which draws itself on a background thread, and even gives you free high-quality zooming when in a UIScrollView... - jjv360

1 Answers

1
votes

You cannot do that: while your drawRect is executing, no other updates to the screen are possible; the spinning gear will not get a chance to be drawn or updated.

If your drawRect takes a few seconds, you should reconsider your strategy: perhaps you could isolate the drawing-intensive code in a function that draws to an in-memory bitmap, show a UIImageView with a placeholder image in place that was to be painted by your drawRect code, do the rendering in a background thread, and replace the image of the UIImageView with what your code has painted.