0

I have an animation involving an object continuously bouncing back and forth between two walls with a time period of 2 seconds between two positions given by the CGPoints 'positionStart' and 'positionEnd'. The code doing this is a pretty simple and basic animation:

CABasicAnimation *theAnimation;
theAnimation=[CABasicAnimation animationWithKeyPath:@"position"];
theAnimation.duration=1.0;
theAnimation.beginTime=CACurrentMediaTime()+1;
theAnimation.repeatCount=HUGE_VALF;
theAnimation.autoreverses=YES;
theAnimation.fromValue=[NSValue valueWithCGPoint:positionStart];
theAnimation.toValue=[NSValue valueWithCGPoint:positionEnd];
[self.pulseLayer addAnimation:theAnimation forKey:@"animatePosition"];

Now here's the question: I want to have this section of code send a message to another object with every "tick" of this clock; that is, every time pulseLayer's presented position goes to 'positionStart' I want this section of code to send a target-action message to another object (let's call it Clock #2) which I want to keep in sync with the periodic bouncing of the 'pulseLayer'.

Is there any simple way of doing this? The best alternative ideas I could come up with are (1) to start an NSTimer at the same time as the start of this animation to send "tick" timing pulses to Clock #2, but I worry that although the NSTimer object and the 'pulseLayer' bounce may start off in sync that small timing errors may build up over time so that they will no longer appear to be in sync after a long time. There would certainly be nothing to force them to remain synchronized. Another idea (2) is to do away with this endless bouncing of pulseLayer (i.e., change theAnimation.repeatCount to equal 0) and have another object send timing pulses to start the one-bounce animation every 2 seconds to both this object and to the "Clock #2" object that I want to keep in sync.

Any ideas about the best way to implement what I want to do here?

Samuel W.
  • 370
  • 1
  • 10
  • 1
    Correct. The trouble is the `autoreverse`. Your answer lies here: http://stackoverflow.com/questions/11515647/objective-c-cabasicanimation-applying-changes-after-animation . You need 2 separate animations, each completed one triggering the start of the next one. No drift guaranteed. – SwiftArchitect Jul 25 '14 at 04:03
  • posted an answer with 2 chained animations which answers the question: **How to synchronize in a repeating animation**. In essence, do *not* use `repeatCount`, but chain your animations using the `delegate`. – SwiftArchitect Jul 25 '14 at 05:05
  • I will remove my comments shortly since they no longer add to the response and only clutter this page (-: – SwiftArchitect Jul 25 '14 at 05:25

1 Answers1

1

autoreverse does not send notification

(until all animations completed, which is never in the example above)

Use 2 different animations. It is simple to setup:

Setup:

// To
self.toAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
self.toAnimation.duration=1.0;
self.toAnimation.fromValue=[NSValue valueWithCGPoint:positionStart];
self.toAnimation.toValue=[NSValue valueWithCGPoint:positionEnd];
self.toAnimation.delegate:self;

// And fro
self.froAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
self.froAnimation.duration=1.0;
self.froAnimation.fromValue=[NSValue valueWithCGPoint:positionEnd];
self.froAnimation.toValue=[NSValue valueWithCGPoint:positionStart];
self.froAnimation.delegate:self;

Start:

// Start the chain of animations by adding the "next" (the first) animation
[self toAndFro:self.froAnimation];

Delegate:

- (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)finished {
    [self toAndFro:(CABasicAnimation*)animation];
}

Core:

- (void)toAndFro:(CABasicAnimation *)stoppedAnimation {
    BOOL wasFro = self.froAnimation == stoppedAnimation;
    CABasicAnimation * theAnimation = ((wasFro)
                                       ? self.toAnimation
                                       : self.froAnimation);

    [self.pulseLayer addAnimation:theAnimation forKey:@"animatePosition"];

    // Tick here! You are now in perfect sync
}
Community
  • 1
  • 1
SwiftArchitect
  • 47,376
  • 28
  • 140
  • 179
  • Absolutely correct. I will still leave my answer as-is: it will work for both clock animations (tic, tac, tic, tac, etc.) or bounce animations (boing, silence, boing, silence, etc.) – SwiftArchitect Jul 25 '14 at 05:24