UIView.layer.presentationLayer returns final value (rather than current value)

我们两清 提交于 2021-02-08 10:53:24

问题


Here's some relevant code inside a UIView subclass:

- (void) doMyCoolAnimation {
  CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath:@"position.x"];
  anim.duration = 4;
  [self.layer setValue:@200 forKeyPath:anim.keyPath];
  [self.layer addAnimation:anim forKey:nil];
}

- (CGFloat) currentX {
  CALayer* presLayer = self.layer.presentationLayer;
  return presLayer.position.x;
}

When I use [self currentX] while the animation is running, I get 200 (the end value) rather than a value between 0 (the start value) and 200. And yes, the animation is visible to the user, so I'm really confused here.

Here's the code where I call doMyCoolAnimation:, as well as currentX after 1 second.

[self doMyCoolAnimation];

CGFloat delay = 1; // 1 second delay
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
  NSLog(@"%f", [self currentX]);
});

Any ideas?


回答1:


I don't know where the idea for using KVC setters in animation code came from, but that's what the animation itself is for. You're basically telling the layer tree to immediately update to the new position with this line:

[self.layer setValue:@200 forKeyPath:anim.keyPath];

Then wondering why the layer tree won't animate to that position with an animation that has no starting or ending values. There's nothing to animate! Set the animation's toValue and fromValue as appropriate and ditch the setter. Or, if you wish to use an implicit animation, keep the setter, but ditch the animation and set its duration by altering the layer's speed.




回答2:


The way you are creating your animation is wrong, as CodaFi says.

Either use an explicit animation, using a CABasicAnimation, or use implicit animation by changing the layer's properties directly and NOT using a CAAnimation object. Don't mix the two.

When you create a CABasicAnimation object, you use setFromValue and/or setToValue on the animation. Then the animation object takes care of animating the property in the presentation layer.




回答3:


My UIView's layer's presentationLayer was not giving me the current values. It was instead giving me the end values of my animation.

 

To fix this, all I had to do was add...

anim.fromValue = [self.layer valueForKeyPath:@"position.x"];

...to my doMyCoolAnimation method BEFORE I set the end value with:

[self.layer setValue:@200 forKeyPath:@"position.x"];

 

So in the end, doMyCoolAnimation looks like this:

- (void) doMyCoolAnimation {
  CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath:@"position.x"];
  anim.duration = 4;
  anim.fromValue = [self.layer valueForKeyPath:anim.keyPath];
  [self.layer setValue:@200 forKeyPath:anim.keyPath];
  [self.layer addAnimation:anim forKey:nil];
}


来源:https://stackoverflow.com/questions/22741496/uiview-layer-presentationlayer-returns-final-value-rather-than-current-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!