facebookarchive / pop

An extensible iOS and OS X animation library, useful for physics-based interactions.
Other
19.66k stars 2.88k forks source link

non identity transform error using kPOPViewScaleXY anim #334

Closed simoami closed 8 years ago

simoami commented 8 years ago

Hello, I'm applying a POPSpringAnimation(propertyNamed: kPOPViewScaleXY) to an ASButtonNode (an AsyncDisplayKit UIButton wrapper). The effect is applied on button touch up. If the effect is applied sequentially in a few seconds intervals, the effect works great each time. But if an effect is applied while the previous one is still in progress, though fast multi taps, I hit the following error:

ASDisplayNodeAssert(
  CATransform3DIsIdentity(self.transform), 
  @"-[ASDisplayNode frame] - self.transform must be identity in order to use the frame property.  (From Apple's UIView documentation: If the transform property is not the identity transform, the value of this property is undefined and therefore should be ignored.)"
);

My code is as follows:

let favoriteButton = ASButtonNode()
func setup() {
    favoriteButton.addTarget(self, action: #selector(self.favoriteButtonPressed), forControlEvents: .TouchUpInside)
}
func favoriteButtonPressed() {
    //favoriteButton.pop_removeAllAnimations()
    //favoriteButton.transform = CATransform3DIdentity
    favoriteButton.pop_addAnimation(getBounceAnim(), forKey: "bounce")
}
func getBounceAnim() -> POPPropertyAnimation {
    let spring = POPSpringAnimation(propertyNamed: kPOPViewScaleXY)
    spring.fromValue = NSValue(CGPoint: CGPointMake(1.5, 1.5))
    spring.toValue = NSValue(CGSize: CGSizeMake(1, 1))
    spring.springBounciness = 15 // a float between 0 and 20
    spring.springSpeed = 10
    spring.beginTime = CACurrentMediaTime()
    return spring
}
grp commented 8 years ago

It looks like you have some code that is setting the frame property while the animation is running. It might be worth checking the backtrace for the assertion failure to find that code, then disabling setting the frame while the animation is running.

simoami commented 8 years ago

@grp I found this:

https://github.com/facebook/AsyncDisplayKit/blob/1.9.90/AsyncDisplayKit/Details/_ASDisplayViewAccessiblity.mm#L88

      [accessiblityElement setAccessibilityFrame:UIAccessibilityConvertFrameToScreenCoordinates(subnode.frame, self)];

which then calls:

- (CGRect)frame
{
  _bridge_prologue_read;

  // Frame is only defined when transform is identity.
#if DEBUG
  // Checking if the transform is identity is expensive, so disable when unnecessary. We have assertions on in Release, so DEBUG is the only way I know of.
  ASDisplayNodeAssert(CATransform3DIsIdentity(self.transform), @"-[ASDisplayNode frame] - self.transform must be identity in order to use the frame property.  (From Apple's UIView documentation: If the transform property is not the identity transform, the value of this property is undefined and therefore should be ignored.)");
#endif

...
}
grp commented 8 years ago

Ah, the issue is in reading the frame. Hmm. That makes things tougher, since it's hard to control that, especially from a UIKit callback.

I'd suggest filing an issue with AsyncDisplayKit to avoid using the frame property there. A short term fix could look something like this:

  [accessiblityElement setAccessibilityFrame:UIAccessibilityConvertFrameToScreenCoordinates(subnode.layer.frame, self)];

That bypasses the AsyncDisplayKit transform check, at the cost of potentially reading subnode.layer.frame when it's technically undefined. A more complete solution would compute the frame manually using the layer's bounds, transform, position, and anchorPoint.

simoami commented 8 years ago

@grp yeah, I see that they fixed the issue in master, the way you suggested:

https://github.com/facebook/AsyncDisplayKit/blob/master/AsyncDisplayKit/Details/_ASDisplayViewAccessiblity.mm#L70-L71

See my comment here: https://github.com/facebook/AsyncDisplayKit/issues/2233#issuecomment-246557804

grp commented 8 years ago

Great! Glad it's figured out.

simoami commented 8 years ago

Thanks!