CALAyer子类中的不可动画属性

Dru*_*rux 2 core-animation objective-c ios7

我定义的一个子类CALayer与动画属性作为讨论在这里.我现在想要为该层添加另一个(不可动画的)属性以支持其内部簿记.

我设置了新属性的值,drawInContext:但我发现在下一次调用时它总是重置为0.这是因为Core Animation假设这个属性也适用于动画,并且它在没有进一步指令的常数0处"动画"它的值吗?在任何情况下,我如何将真正的非动画属性添加到子类CALayer

我找到了一个初步的解决方法,它使用全局CGFloat _property而不是@property (assign) CGFloat property但更喜欢使用普通属性语法.

更新1

这是我尝试在以下位置定义属性的方式MyLayer.m:

@interface MyLayer()

@property (assign) CGFloat property;

@end
Run Code Online (Sandbox Code Playgroud)

这就是我在结尾时给它赋值的方法drawInContext::

self.property = nonZero;
Run Code Online (Sandbox Code Playgroud)

该属性例如在开头时读取drawInContext:如下:

NSLog(@"property=%f", self.property);
Run Code Online (Sandbox Code Playgroud)

更新2

也许这是导致问题(从这个样本继承的代码)?

- (id)actionForKey:(NSString *) aKey {
    if ([aKey isEqualToString:@"someAnimatableProperty"]) {
       CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:aKey];
       animation.fromValue = [self.presentationLayer valueForKey:aKey];
       return animation;
    }
    return [super actionForKey:aKey]; // also applies to my "property"
}
Run Code Online (Sandbox Code Playgroud)

Pie*_*ica 9

要从绘图方法中访问标准属性,在动画期间,您需要进行一些修改.

实现初始化程序

当CoreAnimation执行动画时,它会创建图层的阴影副本,并且每个副本将在不同的帧中呈现.要创建此类副本,它会调用-initWithLayer:.来自Apple的文档:

如果要实现自定义图层子类,则可以覆盖此方法并使用它将实例变量的值复制到新对象中.子类应始终调用超类实现.

因此,您需要实现-initWithLayer:并使用它来手动复制新实例上的属性值,如下所示:

- (id)initWithLayer:(id)layer
{
    if ((self = [super initWithLayer:layer])) {
        // Check if it's the right class before casting
        if ([layer isKindOfClass:[MyCustomLayer class]]) {
            // Copy the value of "myProperty" over from the other layer
            self.myProperty = ((MyCustomLayer *)layer).myProperty;
        }
    }
    return self;
}
Run Code Online (Sandbox Code Playgroud)

通过模型层访问属性

无论如何,副本发生在动画开始之前:你可以通过添加一个NSLog调用来看到这个-initWithLayer:.因此,就CoreAnimation而言,您的财产将始终为零.此外,它创建的副本是只读的,如果您尝试self.myProperty从内部设置-drawInContext:,当在其中一个演示文稿副本上调用该方法时,您会得到一个例外:

*** Terminating app due to uncaught exception 'CALayerReadOnly', reason:  
    'attempting to modify read-only layer <MyLayer: 0x8e94010>' ***
Run Code Online (Sandbox Code Playgroud)

self.myProperty你应该写,而不是设置

self.modelLayer.myProperty = 42.0f
Run Code Online (Sandbox Code Playgroud)

modelLayer将改为参照原来的MyCustomLayer实例中,所有的演示副本共享相同的模型.请注意,在读取变量时也必须执行此操作,而不仅仅是在设置变量时.为了完整性,还应该提及属性presentationLayer,而是返回正在显示的层的当前(副本).