1

The following code is used for a NSButton with wantsLayer set to YES. This works, however if the app is busy processing something in the background, the rotation animation is very choppy:

  POPSpringAnimation *animation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerRotation];
  animation.springBounciness = 8;
  animation.springSpeed = 10;
  animation.toValue = @(M_PI);
  [self.myButton.layer pop_addAnimation:animation forKey:@"rotate"];

I then changed it to the following and it works very smoothly:

 CGAffineTransform transform = CGAffineTransformMakeRotation(-M_PI);

  CABasicAnimation *thAnimation = [ CABasicAnimation animationWithKeyPath: @"transform" ];
  thAnimation.duration = 0.2;

  CATransform3D oldTrans = [self.myButton layer].transform;
  thAnimation.fromValue = [ NSValue valueWithCATransform3D: oldTrans ];
  CATransform3D newTrans = CATransform3DMakeAffineTransform (transform);
  thAnimation.toValue = [ NSValue valueWithCATransform3D: newTrans ];

  [[self.myButton layer] addAnimation: thAnimation forKey: @"rotate" ];
  [[self.myButton layer] setAffineTransform: transform];

I'd like to however still use the POPSpringAnimation instead. I notice it directly uses a DisplayLink timer under the hood. Is there a way to make POP animate my affine transform instead?

strangetimes
  • 4,953
  • 1
  • 34
  • 62
  • What you mean with choppy? I executed both examples and it works fine. – Sam Dec 24 '14 at 11:21
  • By choppy I mean choppy, laggy, missing frames. As I mentioned, while its animating the app is doing some heavy lifting work in the background. That causes it to miss frames as I imagine that some of that processing requires updating the UI on the main thread too. Adding s layer animation however does not lag at all and was wondering if There is a way to not rely on the CADisplayLink timer when doing Pop animations. – strangetimes Dec 25 '14 at 13:22
  • Moreover, it seems if I have a NSAlert showing (runModal), the POP animations just hang mid-way, as if they're not registering themselves properly on to the correct runloop. Can this be fixed too? – strangetimes Dec 25 '14 at 18:44

1 Answers1

1

Okay I've found the problem. In POPAnimator.m the displaylinkCallback method is doing this:

  dispatch_async(dispatch_get_main_queue(), ^{
    [(__bridge POPAnimator*)context render];
  });

Since it's rendering on the main thread, and the main thread of the app is at times busy or blocked, the animation blocks too. All I have to do is enable background thread on POP:

[POPAnimator setDisableBackgroundThread: NO];
strangetimes
  • 4,953
  • 1
  • 34
  • 62
  • I should recommend this is a bad idea as your app may crash unexpectedly while trying to run methods not designed for non-main threads - apparently POP was designed to run on the main thread and so that means if your main thread is busy, your animations are going to be pretty bad looking. Instead you'll need to rely on some custom CAAnimation (which is what I ended up doing). – strangetimes Jan 14 '15 at 21:38