2012-07-15 107 views
0

我正在开发一个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)语句,排队,动画,等待完成,并做到这一点无限。但是,这似乎是一个非常笨重的解决方案。

什么是解决问题的正确设计模式?

回答

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

哇,我是过分复杂的事情。这很奇妙。谢谢! – 2012-07-15 21:45:02

+0

乐意帮忙... – nielsbot 2012-07-15 21:49:16

0

不幸的是只有在Mac OS X 10.7上才有,方法NSAnimationContext可以用来检测动画何时完成(所以,在启动时在某处设置一个标志,并在处理程序中取消该标志的设置标记动画的完成)。通过这种方式,您可以确定在时间段内是否有一些动画正在进行中,另一个动画应该启动。

(我希望有一个更好的办法,但是这是发生在我身上。)

+0

你建议使用像'NSConditionLock'这样的'completionHandler'来阻塞线程,直到动画完成为止? – 2012-07-15 21:02:08