CALAyer子类中的不可动画属性 [英] Non-animatable properties in subclasses of CALAyer

查看:218
本文介绍了CALAyer子类中的不可动画属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经使用动画属性定义了 CALayer 的子类,如上所述此处。我现在想要为该层添加另一个(不可动画的)属性以支持其内部簿记。

I have defined a subclass of CALayer with an animatable property as discussed here. I would now like to add another (non-animatable) property to that layer to support its internal bookkeeping.

我在<$ c $中设置新属性的值c> drawInContext:但是我发现在下次调用时它总是重置为0。是这样的,因为Core Animation假定这个属性也用于动画,并且它在没有进一步指令的常数0处动画它的值?在任何情况下,如何将真正的不可动画属性添加到 CALayer 的子类?

I set the value of the new property in drawInContext: but what I find that it is always reset to 0 when the next call is made. Is this so because Core Animation assumes that this property is also for animation, and that it "animates" its value at constant 0 lacking further instructions? In any case, how can I add truly non-animatable properties to subclasses of CALayer?

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

I have found a preliminary workaround, which is using a global CGFloat _property instead of @property (assign) CGFloat property but would prefer to use normal property syntax.

UPDATE 1

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

This is how I try to define the property in MyLayer.m:

@interface MyLayer()

@property (assign) CGFloat property;

@end

这就是我给它分配值的方法结束 drawInContext:

And this is how I assign a value to it at the end of drawInContext::

self.property = nonZero;

该物业是例如在 drawInContext:的开头读取,如下所示:

The property is e.g. read at the start of drawInContext: like so:

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

更新2

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

Maybe this it was causes the problem (code inherited from this sample)?

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


推荐答案

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

To access your standard property from within the drawing method, during an animation, you need to make a few modifications.

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

When CoreAnimation performs your animation, it creates shadow copies of your layer, and each copy will be rendered in a different frame. To create such copies, it calls -initWithLayer:. From Apple's documentation:


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

If you are implementing a custom layer subclass, you can override this method and use it to copy the values of instance variables into the new object. Subclasses should always invoke the superclass implementation.

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

Therefore, you need to implement -initWithLayer: and use it to copy manually the value of your property on the new instance, like this:

- (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 ,它创建的副本是 readonly ,当在其中一个演示文稿副本上调用该方法时,会出现异常:

Access properties through model layer

The copy, anyway, takes place before the animation starts: you can see this by adding a NSLog call to -initWithLayer:. So as far as CoreAnimation knows, your property will always be zero. Moreover, the copies it creates are readonly, if you try to set self.myProperty from within -drawInContext:, when the method is called on one of the presentation copies, you get an exception:

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

您应该写

self.modelLayer.myProperty = 42.0f

as modelLayer 会将引用到原来的 MyCustomLayer 实例,以及所有演示文稿副本共享相同的模型。请注意,当您阅读变量时,您必须执行此操作,而不仅仅是在设置它时。为了完整性,还应该提及属性 presentationLayer ,而不是返回正在显示的图层的当前(副本)。

as modelLayer will instead refer to the original MyCustomLayer instance, and all the presentation copies share the same model. Note that you must do this also when you read the variable, not only when you set it. For completeness, one should mention as well the property presentationLayer, that instead returns the current (copy of the) layer being displayed.

这篇关于CALAyer子类中的不可动画属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆