使用drawRect设置UIView backgroundColor:

时间:2013-02-24 00:27:27

标签: ios objective-c cocoa performselector setneedsdisplay

我正在尝试设置自定义UIView类的背景颜色。该类还使用drawRect:方法进行石英绘图。

由于在下次重绘视图之前不会发生背景颜色更改,因此我在调用backgroundColor之前更改了UIView的setNeedsDisplay属性。我在视图重绘时设置了UIActivityIndicatorView动画。

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

指标在setNeedsDisplay结束时停止。 theColor每次需要调用时都会更改。

假设我有一段耗时的setNeedsDisplay进程。我想设置背景并保持指标动画。目前,更改backgroundColor调用setNeedsDisplay,但在performSelectorInBackground方法运行之前甚至不更改backgroundColor!因此我的应用程序挂起,没有任何指示器动画。 我该如何处理这个订购问题?谢谢。

编辑:我的意思是我的drawrect:可能很耗时。

2 个答案:

答案 0 :(得分:4)

  

假设我有一个耗时的setNeedsDisplay进程

我们不是。您没有业务覆盖setNeedsDisplay。我对你最终想要完成的事情一点都不清楚,但这整个问题似乎是对如何画画的误解。当你打电话给setNeedsDisplay时(正如你所知,你必须在主线程中做),就是这样;你站在那里,当重绘时刻到来时,你的视图被叫drawRect:。那是画画。

如果问题只是活动指标永远不会发生,那是因为你永远不会给它机会。它也不会在重绘时刻开始。但是你会在重绘时刻之前停止活动指示器!显然你永远不会看到它。

在接下来的事情之前,明确地启动活动指示器的方法是在下一个重绘时刻之后走出主线程。这被称为“延迟表现”。例如:

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
};

您可以通过再次调用dispatch_after来扩展该示例,以便在下一次重绘时刻之后停止指示。

然而,我必须给你留下深刻的印象,如果仅仅是绘画的行为需要一个活动指示器才能覆盖它,你就错了。你的绘画行为必须非常快。您可能希望在此主题上观看WWDC 2012视频;它提供了有效绘制的优秀技巧。

答案 1 :(得分:0)

您只能在主线程上更新UI,而不能在后台更新尝试使用带活动指示符的其他子视图,在重绘之前放入并在超级视图之后删除