Ios UIView.layer.presentationLayer返回最终值(而不是当前值)

Ios UIView.layer.presentationLayer返回最终值(而不是当前值),ios,objective-c,uiview,core-animation,calayer,Ios,Objective C,Uiview,Core Animation,Calayer,以下是UIView子类中的一些相关代码: - (void) doMyCoolAnimation { CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath:@"position.x"]; anim.duration = 4; [self.layer setValue:@200 forKeyPath:anim.keyPath]; [self.layer addAnimation:anim forKey:nil]

以下是UIView子类中的一些相关代码:

- (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;
}
当我在动画运行时使用
[self currentX]
时,我得到的是
200
(结束值),而不是介于
0
(开始值)和
200
之间的。是的,动画对用户是可见的,所以我真的很困惑

下面是我在1秒后调用
doMyCoolAnimation:
,以及
currentX
的代码

[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]);
});

有什么想法吗?

我不知道在动画代码中使用KVC setter的想法是从哪里来的,但这就是动画本身的用途。基本上,您是在告诉图层树立即使用以下行更新到新位置:

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

然后想知道为什么层树不会使用没有起始值或结束值的动画设置到该位置。没有什么可以动画化的!根据需要将动画的
设置为value
fromValue
,然后放弃设置器。或者,如果您希望使用隐式动画,请保留setter,但放弃动画并通过更改层的
速度

来设置其持续时间。我不知道在动画代码中使用KVC setter的想法来自何方,但动画本身就是为了这个目的。基本上,您是在告诉图层树立即使用以下行更新到新位置:

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

然后想知道为什么层树不会使用没有起始值或结束值的动画设置到该位置。没有什么可以动画化的!根据需要将动画的
设置为value
fromValue
,然后放弃设置器。或者,如果您希望使用隐式动画,请保留setter,但放弃动画并通过更改层的
速度来设置其持续时间,正如CodaFi所说,创建动画的方式是错误的

使用显式动画、使用CABASICANIATION或通过直接更改层的特性而不使用CAAnimation对象来使用隐式动画。不要把两者混为一谈


创建CABasicAnimation对象时,可以在动画上使用setFromValue和/或setToValue。然后,动画对象负责为表示层中的属性设置动画。

正如CodaFi所说,创建动画的方式是错误的

使用显式动画、使用CABASICANIATION或通过直接更改层的特性而不使用CAAnimation对象来使用隐式动画。不要把两者混为一谈


创建CABasicAnimation对象时,可以在动画上使用setFromValue和/或setToValue。然后,动画对象负责设置演示层中属性的动画。

我的UIView层的presentationLayer没有为我提供当前值。而是给了我动画的最终价值

要解决这个问题,我所要做的就是添加

anim.fromValue = [self.layer valueForKeyPath:@"position.x"];
…在我的
doMyCoolAnimation
方法之前我使用以下设置结束值:

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

所以最后,
doMyCoolAnimation
看起来是这样的:

- (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];
}

我的UIView图层的presentationLayer没有提供当前值。而是给了我动画的最终价值

要解决这个问题,我所要做的就是添加

anim.fromValue = [self.layer valueForKeyPath:@"position.x"];
…在我的
doMyCoolAnimation
方法之前我使用以下设置结束值:

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

所以最后,
doMyCoolAnimation
看起来是这样的:

- (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];
}

如果在动画添加到层后立即调用getter,则应获得接近0.4的值。尝试将get包装在
dispatch\u after()
@CodaFi中。我知道这一点,并且已经在使用
dispatch\u after()
。我在一个有效的时间检查,但是
presentationLayer
假装它是一个模型层(这是我困惑的根源)。将KVC setter与动画隔离,然后将动画与KVC setter隔离,以了解我的意思。在当前形式下,动画将不起任何作用,KVC setter将使层以默认的隐式动画速度跳转到下一个位置。如果在动画添加到层后立即调用getter,则应获得接近0.4的值。尝试将get包装在
dispatch\u after()
@CodaFi中。我知道这一点,并且已经在使用
dispatch\u after()
。我在一个有效的时间检查,但是
presentationLayer
假装它是一个模型层(这是我困惑的根源)。将KVC setter与动画隔离,然后将动画与KVC setter隔离,以了解我的意思。在当前形式下,动画将不起任何作用,KVC setter将使层以默认的隐式动画速度跳转到下一个位置。可以看到动画正在发生。或者你是说如果我使用卡巴斯卡动画的
toValue
而不是显式动画的隐式动画,那么presentationLayer将被修复。。。这毫无意义。CALayer将尽最大努力设置所有属性更改的动画,但当您尝试提交一个对层不起任何作用的动画时,它将不起任何作用。我想说的是,
setValue:forKeyPath:
并不像您试图做的那样,是创建显式动画的一个步骤。。在我想访问presentationLayer之前,它一直在为我工作。不过,从代码的外观来看,您根本没有遵循他的示例。在那篇博文中没有提到要通过KVC setter。好吧,我知道了。将
fromValue
添加到
CABasicAnimation
使
presentationLayer
返回正确的值!感谢您的帮助@CodaFi。可以看到动画正在发生。或者你是说如果我使用Cabasicanation的
toValue
rat,presentationLayer将被修复