我正在开发一个 OS X 应用程序,其中有一个 NSView 可以跟踪连接状态。如果连接正常,则显示绿点,如果连接断开,则显示红点。
我想使用核心动画来制作动画,但是,在连接状态快速变化的情况下我遇到了麻烦。因为动画发生在另一个线程中,并且不会阻塞,所以当我获取 View 的当前位置时,如果它仍在动画,我会得到介于我想要的之间的东西。
例如,在我的 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
最终会出现错位。
我想看到的是 View 本身动画,等到它完成,然后再次动画本身。
我认为也许解决方案应该是创建一个队列,然后在一个线程中不断将连接状态信息添加到队列中,然后在后台有另一个线程,该线程具有 while(true)
它在其中从该队列中提取、动画、等待完成,并无限地执行此操作。然而,这似乎是一个非常笨拙的解决方案。
解决问题的正确设计模式是什么?
最佳答案
似乎正确的解决方案是了解您想要设置动画的实际值,而不是使用基于 View 当前状态的值(可以是任何值)
- (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;
}
关于objective-c - 顺序核心动画的设计模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11495508/