Reputation: 183
I'm working on a OS X application where I have a NSView that keeps track of connection state. If the connection is up, a green dot is displayed, if the connection is down, a red dot is displayed.
I wanted to animate this using Core Animation, however, I'm having trouble in situations where the connection state changes rapidly. Because the animation occurs in another thread, and doesn't block, when I get the current location of the view, if its still animating, I get something in-between what I want.
For example, within my NSView I have a @property
called connectionState that I am overriding to set the state and animate the green and red dots.
- (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;
}
As I'm sure you can see, if the connection state changes rapidly, self.iconView.frame
is not correct and newPosition
ends up being misaligned.
What I'd like to see is the view animate itself, wait until its complete, then animate itself again.
I've thought perhaps the solution should be to create a queue, then keep adding the connection state information into the queue in one thread, then have another thread in the background that has a while(true)
statement within which it pulls from that queue, animates, waits for completion, and does this ad infinitum. However, this seems like a very clunky solution.
What's the correct design pattern to solve the problem?
Upvotes: 0
Views: 404
Reputation: 16031
Seems like the correct solution is to know the actual values you want to animate to instead of using values based on the current state of your view (which could be anything)
- (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;
}
Upvotes: 1
Reputation: 5431
Unfortunately only available in Mac OS X 10.7, there is a setCompletionHandler:
method on NSAnimationContext
that you could use to detect when the animation is done (so, set a flag somewhere when you start, and unset that flag in the handler to mark the completion of animation). That way you can tell if there is already some animation in progress at the time another animation is supposed to start.
(I hope there is a better way but this is what occurs to me.)
Upvotes: 0