为什么 addAnimation:forKey 在 viewDidLoad 中不工作
Why addAnimation:forKey not working in viewDidLoaded
我有以下由 viewDidLoad 调用的方法。此方法是创建一个 CALayer 来显示图像。该层有一个掩码,其路径是由我的私有方法创建的 UIBezierPath。我想让蒙版无限旋转,然后我给蒙版添加一个CABasicAnimation对象。
- (void) createPathLmask
{
// mask layer
self.pathLayer = [CALayer layer];
self.pathLayer.bounds = CGRectMake(0.0, 0.0, 120, 120);
CGPoint position = self.view.layer.position;
position.y += 140;
self.pathLayer.position = position;
self.pathLayer.backgroundColor = [UIColor redColor].CGColor;
UIImage *backimage = [UIImage imageNamed:@"image2"];
self.pathLayer.contents = (__bridge id)backimage.CGImage;
self.pathLayer.contentsGravity = kCAGravityResizeAspectFill;
// mask
CAShapeLayer *mask = [CAShapeLayer layer];
mask.bounds = CGRectMake(0.0, 0.0, 120, 120);
mask.position = CGPointMake(60.0f, 60.0f);
mask.contentsGravity = kCAGravityResizeAspectFill;
mask.path = [self createBezierPathInRect:mask.bounds].CGPath;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// rotate the mask repeatedly
CABasicAnimation *animation = [CABasicAnimation animation];
animation.keyPath = @"transform.rotation";
animation.duration = 4.0f;
animation.byValue = @(M_PI * 2);
animation.repeatCount = HUGE_VALF;
[mask addAnimation:animation forKey:@"rotation_repeatedly"];
});
self.pathLayer.mask = mask;
[self.view.layer addSublayer:self.pathLayer ];
}
我发现旋转动画只有在我将addAnimation:forKey 放入dispatch_after 块并延迟1 秒时才能工作。如果这些代码被移出块,掩码将不会旋转。
所以在viewDidLoaded中给layer添加动画的时候一定是有什么东西没有准备好。我想知道什么还没有准备好?有没有合适的机会添加动画的文档或解释?
So there must be something not ready when animation is added to the layer in viewDidLoaded
正确。这对于动画来说还为时过早。请记住,此时的视图仅仅存在,仅此而已;它甚至不是界面的一部分。您不能为不属于视图层次结构的视图设置动画。此时没有任何动画。
视图首先成为第一次调用 viewWillAppear
和第一次调用 viewDidAppear
之间的接口的一部分。这就是 "appear" 的意思(相对于 "loaded" 的意思)。
Apple 网站 here 上有很棒的文档。简单地说:
- ViewWillAppear - 在将视图控制器的视图添加到视图层次结构之前以及为显示视图配置任何动画之前调用此方法。您可以覆盖此方法以执行与显示视图关联的自定义任务。例如,您可以使用此方法更改状态栏的方向或样式,以与呈现的视图的方向或样式相协调。
我有以下由 viewDidLoad 调用的方法。此方法是创建一个 CALayer 来显示图像。该层有一个掩码,其路径是由我的私有方法创建的 UIBezierPath。我想让蒙版无限旋转,然后我给蒙版添加一个CABasicAnimation对象。
- (void) createPathLmask
{
// mask layer
self.pathLayer = [CALayer layer];
self.pathLayer.bounds = CGRectMake(0.0, 0.0, 120, 120);
CGPoint position = self.view.layer.position;
position.y += 140;
self.pathLayer.position = position;
self.pathLayer.backgroundColor = [UIColor redColor].CGColor;
UIImage *backimage = [UIImage imageNamed:@"image2"];
self.pathLayer.contents = (__bridge id)backimage.CGImage;
self.pathLayer.contentsGravity = kCAGravityResizeAspectFill;
// mask
CAShapeLayer *mask = [CAShapeLayer layer];
mask.bounds = CGRectMake(0.0, 0.0, 120, 120);
mask.position = CGPointMake(60.0f, 60.0f);
mask.contentsGravity = kCAGravityResizeAspectFill;
mask.path = [self createBezierPathInRect:mask.bounds].CGPath;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// rotate the mask repeatedly
CABasicAnimation *animation = [CABasicAnimation animation];
animation.keyPath = @"transform.rotation";
animation.duration = 4.0f;
animation.byValue = @(M_PI * 2);
animation.repeatCount = HUGE_VALF;
[mask addAnimation:animation forKey:@"rotation_repeatedly"];
});
self.pathLayer.mask = mask;
[self.view.layer addSublayer:self.pathLayer ];
}
我发现旋转动画只有在我将addAnimation:forKey 放入dispatch_after 块并延迟1 秒时才能工作。如果这些代码被移出块,掩码将不会旋转。
所以在viewDidLoaded中给layer添加动画的时候一定是有什么东西没有准备好。我想知道什么还没有准备好?有没有合适的机会添加动画的文档或解释?
So there must be something not ready when animation is added to the layer in viewDidLoaded
正确。这对于动画来说还为时过早。请记住,此时的视图仅仅存在,仅此而已;它甚至不是界面的一部分。您不能为不属于视图层次结构的视图设置动画。此时没有任何动画。
视图首先成为第一次调用 viewWillAppear
和第一次调用 viewDidAppear
之间的接口的一部分。这就是 "appear" 的意思(相对于 "loaded" 的意思)。
Apple 网站 here 上有很棒的文档。简单地说:
- ViewWillAppear - 在将视图控制器的视图添加到视图层次结构之前以及为显示视图配置任何动画之前调用此方法。您可以覆盖此方法以执行与显示视图关联的自定义任务。例如,您可以使用此方法更改状态栏的方向或样式,以与呈现的视图的方向或样式相协调。