我有一个简单的UIView,使用drawRect:
绘制自己。为了使视图具有动画效果,需要每隔0.05秒调用drawRect
方法,因此我使用重复计时器:
timer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self
selector:@selector(setNeedsDisplay) userInfo:nil repeats:YES];
我对运行循环,线程以及所有系统内容都不太了解,所以我想知道这是否是运行动画的正确方法?这个计时器无休止地重复。这是我应该担心的吗?这会阻塞主线程吗?我该怎么做才能最大限度地降低对绩效的整体影响?
答案 0 :(得分:2)
方法并不差,但还有其他方法可以做到。
计时器的目标方法必须将计时器作为参数,因此不应直接为setNeedsDisplay设置,而应设置如下方法:
- (void)animationTimerDidFire:(NSTimer *)timer
{
[myView setNeedsDisplay];
}
如果您的视图始终可见,那么您可以设置并忘记计时器。另一方面,如果因为切换到不同的视图而可能会消失,则需要根据需要使计时器无效并重新创建。
您的应用程序的主线程使用运行循环并调用各种方法来响应事件,例如用户点击,系统通知(例如,内存警告)和I / O到达。如果运行循环调用需要很长时间才能返回,它将占用队列中的所有内容。设置计时器时,会将其添加到列表中,并且运行循环每次都会检查它;如果其中一个计时器准备就绪,它会调用你的方法。
最终的结果是计时器不准确:它们可能不会像你喜欢的那样频繁发射,可能会被称为迟到等。再次,如果你的应用程序非常简单,主运行循环将不会非常繁忙所以计时器可能会足够好。只需确保您的动画基于通话之间经过的实际时间,而不是假设每次通话恰好相隔0.05秒。
如果你的动画只是翻阅一些静态图像,UIImageView对此有一些支持。
如果创建每个动画帧花费了相当多的时间(并且您不想阻止主线程),则可以使用后台队列来绘制图像(请参阅CGBitmapContextCreate
和{{ 1}}),然后在准备好显示新图像时发出主线程信号。任何触及视图的东西必须发生在主线程上,但你可以在后台进行绘图。
您可能还想阅读QuartzCore框架中的CGBitmapContextCreateImage
。这就是UIView对象实际操作以在屏幕上绘制的内容。您可能会发现,您可以通过操纵某些CALayer对象并让Core Animation完成繁重的操作来获得您想要的效果(例如,您将颜色从红色更改为蓝色,Core Animation会将淡入淡出从一个变为蓝色,而不是绘制另一个)。
答案 1 :(得分:0)
好吧,如果您使用的是重写或自定义方法,则应使用递归和完成块来调用动画。我发现它比定时器更好用,因为定时器并不总是准确的,如果你有动画定时骑行,可能会引起一些动画问题。
编辑:我不太了解使用drawRect:并调用[self setNeedsDisplay]来更新它,所以在这方面我无法帮助你。遗憾。