我有一个复杂的Quartz例程,drawRect
用于自定义UIView
子类。绘制可能需要几秒钟。我想在绘画时展示UIActivityIndicator
。但是,在绘图完成后,指示器必须停止旋转(并隐藏)。
我尝试启动指标的动画,然后将 performSelector
用于仅调用setNeedsDisplay
的自定义方法 - 我的想法是performSelector
会等到下一次运行循环,对吧?在这种情况下,我的指标有时间在主线程上启动。这似乎有效,但是一旦我将代码添加到drawRect
末尾以停止动画,指示器根本不显示,就好像这个动画在有机会开始之前就结束了。
有什么建议吗?
我这样称呼这幅画:
[self.spinner startAnimating];
[self performSelectorOnMainThread:@selector(redraw) withObject:nil waitUntilDone:YES];//tried both YES and NO here
-(void)redraw{
[self.customView setNeedsDisplay];
}
drawRect:
最后只是这样:
- (void)drawRect:(CGRect)rect{
//bunch of drawing
[self.nav stopSpinner]; // reference to a controller class
}
self.nav
对象是这样的:
-(void)stopSpinner{
self.spinner.hidden=YES;
[self.spinner stopAnimating];
}
spinner
对象最初是这样创建的:
self.spinner=[[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]autorelease];
self.spinner.hidden=YES;
[self.viewController.view addSubview:self.spinner];
在后台线程上执行绘图。这不仅可以让您抛出活动指示器并根据需要进行动画处理,而且绘图本身的速度要快得多。在我的测试中,我看到在背景线程上绘制复杂的石英的速度提高了 10 倍。
这并不难。事实上,它可能非常快,你不需要活动指示器。
下面是代码,您可以简单地使用常规UIImageView
,然后将其 image
属性分配给来自其他线程的呈现输出:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
UIGraphicsBeginImageContext(self.bounds.size);
CGContextRef context = UIGraphicsGetCurrentContext();
//perform some drawing into this context
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
dispatch_sync(dispatch_get_main_queue(), ^{
self.imageView.image=viewImage;
});
});