【问题标题】:Non-animatable properties in subclasses of CALAyerCALAyer 子类中的非动画属性
【发布时间】:2014-08-27 04:19:33
【问题描述】:

我已经定义了CALayer 的一个子类,它具有here 所讨论的动画属性。我现在想向该层添加另一个(非动画)属性以支持其内部簿记。

我在drawInContext: 中设置了新属性的值,但我发现在下一次调用时它总是重置为0。是不是因为 Core Animation 假设这个属性也是用于动画的,并且它在没有进一步说明的情况下将其值“动画化”为常量 0?无论如何,我怎样才能将真正不可动画的属性添加到CALayer 的子类?

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

更新 1

这就是我尝试在MyLayer.m 中定义属性的方式:

@interface MyLayer()

@property (assign) CGFloat property;

@end

这就是我在drawInContext: 末尾为其赋值的方式:

self.property = nonZero;

该属性是例如在drawInContext: 的开头阅读如下:

NSLog(@"property=%f", self.property);

更新 2

也许这是导致问题的原因(代码继承自 this 示例)?

- (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"
}

【问题讨论】:

  • 你能说明一下这个属性是如何定义的,它的值是如何设置的以及它们在哪里被读取?
  • @DavidRönnqvist 完成。
  • 您是否尝试在动画期间读取值?
  • 你在-initWithLayer:做什么?

标签: objective-c ios7 core-animation


【解决方案1】:

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

实现初始化程序

当 CoreAnimation 执行您的动画时,它会创建图层的阴影副本,并且每个副本将在不同的帧中呈现。要创建这样的副本,它会调用-initWithLayer:。 来自Apple's documentation

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

因此,您需要实现-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;
}

通过模型层访问属性

无论如何,复制发生在动画开始之前:您可以通过将NSLog 调用添加到-initWithLayer: 来查看这一点。因此,据 CoreAnimation 所知,您的属性将始终为零。此外,它创建的副本是只读,如果您尝试从-drawInContext: 中设置self.myProperty,当在其中一个演示副本上调用该方法时,您会得到一个异常:

*** Terminating app due to uncaught exception 'CALayerReadOnly', reason:  
    'attempting to modify read-only layer <MyLayer: 0x8e94010>' ***

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

self.modelLayer.myProperty = 42.0f

因为modelLayer 将改为引用原始MyCustomLayer 实例,并且所有演示文稿副本共享相同的模型。请注意,您必须在读取变量时也这样做,而不仅仅是在设置变量时。为了完整起见,还应提及属性presentationLayer,它会返回当前显示的(该图层的副本)。

【讨论】:

    猜你喜欢
    • 2011-01-24
    • 1970-01-01
    • 2011-03-11
    • 1970-01-01
    • 2013-08-19
    • 2010-12-06
    • 2015-08-13
    • 2015-12-10
    • 1970-01-01
    相关资源
    最近更新 更多