0

我正在开发一个 OS X 应用程序,其中我有一个 NSView 来跟踪连接状态。如果连接正常,则显示一个绿点,如果连接断开,则显示一个红点。

我想使用 Core Animation 对此进行动画处理,但是,在连接状态快速变化的情况下我遇到了麻烦。因为动画发生在另一个线程中,并且不会阻塞,所以当我获得视图的当前位置时,如果它仍然在动画,我会得到我想要的东西。

例如,在我的 NSView 中,我有一个@property名为 connectionState 的我正在覆盖它来设置状态并为绿点和红点设置动画。

- (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)语句,它从该队列中拉出,动画,等待完成,并无限地执行此操作。然而,这似乎是一个非常笨拙的解决方案。

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

4

2 回答 2

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;
}
于 2012-07-15T21:07:57.390 回答
0

不幸的是,仅在 Mac OS X 10.7 中可用,有一种setCompletionHandler:方法NSAnimationContext可用于检测动画何时完成(因此,在开始时在某处设置标志,并在处理程序中取消设置该标志以标记动画完成) . 这样你就可以知道在另一个动画应该开始的时候是否已经有一些动画正在进行中。

(我希望有更好的方法,但这就是我发生的事情。)

于 2012-07-15T20:54:40.983 回答