我正在开发一个OS X应用程序,我有一个跟踪连接状态的NSView。如果连接已启动,则会显示绿点,如果连接断开,则会显示一个红点。
我想使用Core Animation制作动画,但是,在连接状态快速变化的情况下,我遇到了麻烦。因为动画发生在另一个线程中,并且没有阻塞,当我得到视图的当前位置时,如果它仍然是动画,我得到的东西介于我想要的之间。
例如,在我的NSView中,我有一个名为connectionState的@property
,我将覆盖以设置状态并为绿色和红色点设置动画。
- (void)setConnectionState:(BOOL)online
{
NSPoint newPosition;
if (online) {
newPosition = NSMakePoint(self.iconView.frame.origin.x,
self.iconView.frame.origin.y + 32);
} else {
newPosition = NSMakePoint(self.iconView.frame.origin.x,
self.iconView.frame.origin.y - 32);
}
[NSAnimationContext beginGrouping];
[[NSAnimationContext currentContext] setDuration:0.5];
[self.iconView.animator setFrameOrigin:newPosition];
[NSAnimationContext endGrouping];
_connectionState = online;
}
我相信您可以看到,如果连接状态快速变化,self.iconView.frame
不正确,newPosition
最终未对齐。
我希望看到的是视图动画本身,等待它完成,然后再次动画。
我想也许解决方案应该是创建一个队列,然后继续在一个线程中将连接状态信息添加到队列中,然后在后台创建一个具有while(true)
语句的另一个线程拉动该队列,动画,等待完成,并无限制地执行此广告。然而,这似乎是一个非常笨重的解决方案。
解决问题的正确设计模式是什么?
答案 0 :(得分:1)
似乎正确的解决方案是知道要设置动画的实际值,而不是根据视图的当前状态(可能是任何内容)使用值
- (void)setConnectionState:(BOOL)online
{
const NSPoint kViewOnPosition = {...} ;
const NSPoint kViewOffPosition = {...} ;
NSPoint newPosition = online ? kOnPosition : kOffPosition ;
[NSAnimationContext beginGrouping];
[[NSAnimationContext currentContext] setDuration:0.5];
[self.iconView.animator setFrameOrigin:newPosition];
[NSAnimationContext endGrouping];
_connectionState = online;
}
答案 1 :(得分:0)
不幸只有在Mac OS X 10.7中可用,setCompletionHandler:
上有一个NSAnimationContext
方法可以用来检测动画何时完成(所以,当你开始时在某个地方设置一个标志,并且取消设置处理程序中的标志以标记动画的完成)。这样你可以判断在另一个动画应该开始的时候是否已经有一些动画正在进行中。
(我希望有更好的方法,但这就是我的想法。)