Set UIView backgroundColor with drawRect:

冷暖自知 提交于 2019-12-08 10:26:37

问题


I am trying to set a custom UIView class's background color. The class also does quartz drawing in the drawRect:method.

Since background color change does not take place until the next redraw of the view, I change the UIView's backgroundColor property before calling setNeedsDisplay. I have set a UIActivityIndicatorView to animate while the view is redrawing.

self.backgroundColor = theColor; 
[indicator startAnimating];
[self performSelectorInBackground:@selector(setNeedsDisplay) withObject:nil];

The indicator is stopped at the end of setNeedsDisplay. theColor will change every time I need to call this.

Let's say I have a time consuming setNeedsDisplay process. I would like to set the background and keep the indicator animation. Currently, changing backgroundColor calls setNeedsDisplay but doesn't even change the backgroundColor until the performSelectorInBackground method runs! Therefore my app hangs and no indicator is ever animated. How do I deal with this ordering problem? Thanks.

Edit: I meant that my drawrect: may be time consuming.


回答1:


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.




回答2:


You can update UI only on Main thread, not in backgroung

Try to use another subview with activity indicator, put in on before redraw and remove from superview after



来源:https://stackoverflow.com/questions/15047346/set-uiview-backgroundcolor-with-drawrect

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!