我有一个CALayer
的子类,它有一个自定义属性,声明如下:
@interface MyLayer : CALayer
@property (nonatomic,retain) NSNumber *customValue;
@end
@implementation MyLayer
@synthesize customValue = _customValue;
@end
我想在显式CATranasction
中设置此属性的动画,所以我使用实现的actionForLayer:forKey:
方法设置了一个委托,该方法返回动画,但是在[CATransaction begin] ... [CATransaction end]
中对someMyLayerInstance.customValue
的任何更改都不会导致actionForLayer:forKey
被调用相应的"key"值。
但是,通过调用setValue:forKey:
对MyLayer
上的属性进行核处理并更改myLayerInstance
会导致调用actionForLayer:forKey:
。
这似乎是因为CALayer
为未定义属性的键/值编码做了一些技巧。我如何重新创建这个魔力,以便在MyLayer
上声明属性,但仍然让动画代理观察它们?
最重要的是,您需要使用@dynamic
实现所有CALayer
访问器。不要使用@synthesize
,也不要直接实现访问器。CALayer
生成它自己的所有属性处理程序(正如您间接发现的那样),您需要使用这些处理程序。
您还需要让CALayer
知道此属性会影响显示(您可能已经在给出其他注释的情况下这样做了)。如果您还没有,您可以通过实现+needsDisplayForKey:
并返回密钥的YES
来完成此操作。
以下是一个为自定义属性设置动画的CALayer
示例(取自iOS 5编程突破极限的第7章。完整的示例代码可在Wiley网站上获得。)此示例在层中实现actionForKey:
,但如果您愿意,您仍然可以在委托中实现该部分。
@implementation CircleLayer
@dynamic radius;
...
+ (BOOL)needsDisplayForKey:(NSString *)key {
if ([key isEqualToString:@"radius"]) {
return YES;
}
return [super needsDisplayForKey:key];
}
- (id < CAAction >)actionForKey:(NSString *)key {
if ([self presentationLayer] != nil) {
if ([key isEqualToString:@"radius"]) {
CABasicAnimation *anim = [CABasicAnimation
animationWithKeyPath:@"radius"];
anim.fromValue = [[self presentationLayer]
valueForKey:@"radius"];
return anim;
}
}
return [super actionForKey:key];
}
@end