Let's say I have a time consuming setNeedsDisplay process
Let's not. You have no business overriding setNeedsDisplay
. I am not at all clear on what you're ultimately trying to accomplish but this entire question seems to be a misunderstanding of how to draw. When you call setNeedsDisplay
(which, as you've been told, you must do in the main thread), that's that; you stand out of the way, and when the redraw moment comes, your view's drawRect:
is called. That's drawing.
If the problem is simply that the activity indicator never gets going, that's because you never give it a chance. It too is not going to start going until the redraw moment. But you are stopping the activity indicator before the redraw moment even comes! So obviously you'll never see it go.
The way to start an activity indicator visibly before the next thing you do is to step out to the main thread after the next redraw moment. This is called "delayed performance". Example:
self.backgroundColor = theColor;
[indicator startAnimating];
double delayInSeconds = 0.1;
dispatch_time_t popTime =
dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
// do something further, e.g. call setNeedsDisplay
};
You could extend that example by calling dispatch_after
yet again to stop the indicator after the next redraw moment.
I must impress upon you, however, that if the mere act of drawing takes so long that you need an activity indicator to cover it, you're drawing wrong. Your act of drawing must be very very fast. You might want to watch the WWDC 2012 video on this very topic; it gives excellent tips on how to draw efficiently.