如何让CAAnimation在每个动画节目中调用块?

ale*_*son 5 core-animation objective-c ios

我可以以某种方式在CAAnimation的每个"tick"上执行一个块吗?它可能像下面的代码一样工作.如果有一种方法可以使用选择器,这也有效.

NSString* keyPath = @"position.x";
CGFloat endValue = 100;

[CATransaction setDisableActions:YES];
[self.layer setValue:@(toVal) forKeyPath:keyPath];

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:keyPath];
animation.duration = 1;
animation.delegate = self;

__weak SelfClass* wself = self;
animation.eachTick = ^{
    NSLog(@"Current x value: %f", [wself valueForKeyPath:keypath]);
};

[self.layer addAnimation:animation forKey:nil];
Run Code Online (Sandbox Code Playgroud)

Rob*_*Rob 11

典型的技术是使用显示链接(CADisplayLink).

因此,为显示链接定义一个属性:

@property (nonatomic, strong) CADisplayLink *displayLink;
Run Code Online (Sandbox Code Playgroud)

然后实现启动,停止和处理显示链接的方法:

- (void)startDisplayLink
{
    self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)];
    [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
}

- (void)stopDisplayLink
{
    [self.displayLink invalidate];
    self.displayLink = nil;
}

- (void)handleDisplayLink:(CADisplayLink *)displayLink
{
    CALayer *layer = self.animatedView.layer.presentationLayer;

    NSLog(@"%@", NSStringFromCGRect(layer.frame));
}
Run Code Online (Sandbox Code Playgroud)

请注意,虽然视图是动画,但您无法查看其基本属性(因为它将反映最终目的地而不是"飞行中"位置),而是访问动画视图的图层presentationLayer,如上所示.

无论如何,在开始动画时启动显示链接.并在完成后将其删除.

使用标准的基于块的动画,您可以执行以下操作:

[UIView animateWithDuration:2.0 delay:0 options:0 animations:^{
    view.frame = someNewFrame;
} completion:^(BOOL finished) {
    [self stopDisplayLink];
}];

[self startDisplayLink];
Run Code Online (Sandbox Code Playgroud)

使用Core Animation,它可能看起来像:

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
animation.fromValue = [NSValue valueWithCGPoint:startPoint];
animation.toValue = [NSValue valueWithCGPoint:endPoint];

[CATransaction setAnimationDuration:1.0];
[CATransaction setCompletionBlock:^{
    [self stopDisplayLink];
}];

[CATransaction begin];
[self.animatedView.layer addAnimation:animation forKey:nil];
[CATransaction commit];

[self startDisplayLink];
Run Code Online (Sandbox Code Playgroud)