在核心动画当中是分两个图层的,一个是显示图层,一个是模型图层
我们给UIView的属性frame和backgroundColor赋值其实都是赋值给了模型图层,这个模型图层就保存了这些值,我们的显示图层是实时更新的
CALayer的属性行为其实很不正常,因为改变一个图层的属性并没有立刻生效,而是通过一段时间渐变更新
当我们去设置CALayer的属性,其实就是定义在当前事务结束之后图层如何去显示的模型数据,也就是说CALayer只是知道的是我们设置的值,但是中间我们使用动画设置实时变化的值是不知道的
在iOS中,屏幕每秒钟重绘60次。如果动画时长比60分之一秒要长,Core Animation就需要在设置一次新值和新值生效之间,对屏幕上的图层进行重新组织。所以这意味着CALayer除了“真实”值(就是你设置的值)之外,必须要知道当前显示在屏幕上的属性值的记录。所以就有了呈现图层
每个图层属性的显示值都被存储在一个叫做呈现图层的独立图层当中,他可以通过-presentationLayer方法来访问。这个呈现图层实际上是模型图层的复制,但是它的属性值代表了在任何指定时刻当前外观效果。换句话说,你可以通过呈现图层的值来获取当前屏幕上真正显示出来的值
呈现图层仅仅当图层首次被提交(就是首次第一次在屏幕上显示)的时候创建,所以在那之前调用-presentationLayer将会返回nil,就比如说下面我们去创建一个UIView,然后不让它在屏幕上去显示出来,然后去打印下其的presentationLayer属性
我们可以通过presentationLayer去获取modelLayer。这其实就是在呈现图层上调用–modelLayer将会返回它正在呈现所依赖的CALayer。通常在一个图层上调用-modelLayer会返回–self(实际上我们已经创建的原始图层就是一种数据模型)这里再看下打印这两个属性的效果
以及我们在使用基本核心动画CABasicAnimation的时候,我们去创建动画对象,然后我们去进行设置动画的数学,然后去将这个动画加到layer上面,就可以进行动画的展示了
CABasicAnimation * animation = [CABasicAnimation animation];
animation.keyPath = @"position.y";
animation.toValue = @400;
[view.layer addAnimation:anim forKey:nil];
但是这样动画结束之后还是会回到动画开始的位置,如果我们想要不让动画回到开始的位置我们还可以设置下面的两个属性
//当为true时,当动画的活动持续时间已经过时,动画将从渲染树中删除。默认值为YES。
animation.removedOnCompletion = NO;
//当动画完成时,我们的layer在其最终状态中仍然可见
animation.fillMode = kCAFillModeForwards;
当然还有另外的方法就是不要去设置animation.toValue和removedOnCompletion以及fillMode的设置我们也可以不用去设置了,我们只需要去修改我们需要改变的layer的frame其实就可以了,当然改变view的frame也是一样的,最后会影响到相应的layer,但是我们如果采用animation.tovalue就不会影响到其的layer和UIView的frrame
view.frame = CGRectMake(50, 400, 100, 100);
之所以我们去设置了animation的tovalue,会回到原点的原因就在于,通过动画来改变其的位置,模型图层的属性值frame是没有变化的,变的其实是显示图层的frame,但是这个呈现图层一旦动画结束之后会变回和模型图层一样的值,我们在下面的这个动画结束的代理方法中去打印UIView.layer的frame和UIView.layer.presentationLayer的frame,我们会发现,layer的frame是没有变化的还是和UIView的frame一样没有随着动画而改变其的frame,但是presentationLayer是改变了的
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
}