前言
关于CAAnimation和CALayer类,核心动画扩展了NSKeyValueCoding协议。这个扩展为一些keys添加了默认值,扩大了封装协议,添加了为CGpoint、CGRect、CGSize和CATransform3D类型的支持。
KVC支持的集成类
CAAnimation和CALayer类是支持KVC的,这意味着我们可以为任意的Keys赋值。即使是CALayer类没有声明的Key属性,我们仍旧可以为它赋值,如下:
[theLayer setValue:[NSNumber numberWithInteger:50] forKey:@"someKey"];
我们也可以使用任意的Keys获取对应的value,例如,获取先前用someKey设置的value:
someKeyValue=[theLayer valueForKey:@"someKey"];
默认值的支持
核心动画为KVC添加了扩展,当没有为某个Key设置值的时候,将会提供一个默认值。CAAnimation和CALayer类支持这个扩招,通过使用defaultValueForKey:类方法。
为了为Key提供默认值,创建要使用的类的子类,并重写这个defaultValueForKey: 方法。我们实现该方法时需要先检查Key参数并返回合适的默认值。代码C-1展示了defaultValueForKey: 的实现,此处为masksToBounds属性提供默认值。
代码C-1 实现defaultValueForKey:的示例
+ (id)defaultValueForKey:(NSString *)key
{
if ([key isEqualToString:@"masksToBounds"])
return [NSNumber numberWithBool:YES];
return [super defaultValueForKey:key];
}
封装方式
当Key对应的value是有标量值或者C的结构体时,我们必须在将value关联到Layer之前,把value封装为对象类型。相似的,当获取这些类型的vlaue时,我们必须拆封相应的value使用相应的扩展类。表C-1列出了通常使用的C类型和常用的用于封装的OC类。
Table C-1 用于C类型封装的OC类
C 类型 | 封装类型 |
---|---|
CGPoint | NSValue |
CGSize | NSValue |
CGRect | NSValue |
CATransform3D | NSValue |
Key Path支持结构体
通过使用Key paths,CAAnimation和CALayer类让我们获得选中的数据类型的某个值。这种方式是非常便利的,对于指定某个我们想要的做动画的数据类型的某个值。我们可以利用这种便利方式通过使用setValue:forKeyPath:和valueForKeyPath:方法设置和获取这些值。
CATransform3D Key path
我们可以使用强大的key path(支持获取某个数据类型为CATransform3D的属性的特定的transformation某个值) 。为了为Layer的transform指定完整的key path,我们应该使用表C-2中transform或sublayerTransform的一个结构的字符值。例如为了指定绕Layer的Z轴的旋转因子,我们应该使用key path为transform.rotation.z。
Table C-2 Transform 分支的Key paths
Key path 分支 | 描述 |
---|---|
rotation.x | 设置值为旋转弧度的NSNumber对象,x轴 |
rotation.y | 设置值为旋转弧度的NSNumber对象,y轴 |
rotation.z | 设置值为旋转弧度的NSNumber对象,z轴 |
rotation | 设置值为旋转弧度的NSNumber对象,z轴,这个默认就是设置rotation.z |
scale.x | 设置代表缩放因子的NSNumber对象,x轴 |
scale.y | 设置代表缩放因子的NSNumber对象,y轴 |
scale.z | 设置代表缩放因子的NSNumber对象,z轴 |
scale | 设置代表缩放因子的NSNumber对象,x,y,z轴 |
translation.x | 设置代表平移量的NSNumber对象,x轴 |
translation.y | 设置代表平移量的NSNumber对象,y轴 |
translation.z | 设置代表平移量的NSNumber对象,z轴 |
translation | 设置包含一个NSSize或CGSize数据类型的NSValue对象。那个数据将会指定在x和y轴上平移的量 |
下面的例子展示了我们如何使用setValue:forKeyPath:方法修改Layer。这个例子设置translation的X轴因子为10点,引起layer移动相应的量在X轴。
[myLayer setValue:[NSNumber numberWithFloat:10.0] forKeyPath:@"transform.translation.x"];
注意:使用key paths设置values和通过OC属性赋值是不一样的。我们不能直接使用属性的符号来设置transform内的值,我们必须使用setValue:forKeyPath:方法和上面指出的key path字符串。
CGPoint Key Paths
如果某个属性的值是CGPoint类型,我们为路径必须拼接表C-3中的一个分量,才能获得和设置相应的值。例如改变一个Layer的position属性的x分量,我们应该将key Path 写成position.x。
Table C-3 CGPoint数据类型的分量
结构体分量 | 描述 |
---|---|
x | 点的x分量 |
y | 点的y分量 |
CGSize Key Paths
如果某个属性的值是CGSize类型,我们为路径必须拼接表C-4中的一个分量,才能获得和设置相应的值。
Table C-3 CGPoint数据类型的分量
结构体分量 | 描述 |
---|---|
width | size的宽度分量 |
height | size的高度分量 |
CGRect Key Paths
如果某个属性的值是CGRect类型,我们为路径必须拼接表C-5中的一个分量,才能获得和设置相应的值。例如,为了改变Layer的bounds属性的宽度分量,我们应该写成bounds.size.width。
Table C-3 CGPoint数据类型的分量
结构体分量 | 描述 |
---|---|
origin | 矩形的原点,类型为CGPoint |
orgin.x | 矩形原点的x分量 |
orgin.y | 矩形原点的y分量 |
size | 矩形的尺寸,类型为CGSize |
size.width | 矩形尺寸的宽度分量 |
size.height | 矩形的尺寸的高度分量 |