Non-animatable properties in subclasses of CALAyer

前端 未结 1 1157
长发绾君心
长发绾君心 2021-01-21 16:30

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 suppo

相关标签:
1条回答
  • 2021-01-21 17:01

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

    Implement initializer

    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.

    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;
    }
    

    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>' ***
    

    Instead of setting self.myProperty, you should write

    self.modelLayer.myProperty = 42.0f
    

    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.

    0 讨论(0)
提交回复
热议问题