Note that there are some explanatory texts on larger screens.

plurals
  1. POHow exactly to subclass CALayer and use a custom property?
    primarykey
    data
    text
    <p>I am trying to create a subclass of <code>CALayer</code> with a custom <code>index</code> property that I can both animate and change directly in order to display a different picture based on the index.</p> <p>In the header, I declared:</p> <pre><code>@property NSUInteger index; </code></pre> <p>In the implementation, I overrode <code>needDisplayForKey</code>:</p> <pre><code>+ (BOOL)needsDisplayForKey:(NSString *)key { if ([key isEqualToString:@"index"]) return YES; else return [super needsDisplayForKey:key]; } </code></pre> <p>Now, in the <code>display</code> method, I want to display a picture based on the index. However, during an animation, the value of <code>self.index</code> never changes, so I have to query the value of the presentation layer, contrary to the example on <a href="https://developer.apple.com/library/mac/#documentation/cocoa/conceptual/coreanimation_guide/Articles/ProvidingCALayerContent.html#//apple_ref/doc/uid/TP40006642-SW1" rel="noreferrer">Providing CALayer Content by Subclassing</a>:</p> <pre><code>- (void)display { NSUInteger presentationIndex = [(CustomLayer *)[self presentationLayer] index]; self.contents = (id)[[images objectAtIndex:presentationIndex] CGImage]; } </code></pre> <p>The problem is, if I do that, I cannot set the <code>index</code> value directly outside of an animation, because it will only change the model layer, and the <code>display</code> method explicitly queries the presentation layer.</p> <p>If I add an initialization method that copies the value of <code>index</code>, it works:</p> <pre><code>- (id)initWithLayer:(id)layer { self = [super initWithLayer:layer]; if (self) { if ([layer isKindOfClass:[CustomLayer class]]) self.index = [(CustomLayer *)layer index]; } return self; } </code></pre> <p>However, after or before an animation, there is always a 1 image glitch because the presentation or the model value don't match (depending if I set <code>index</code> to the destination value or not).</p> <ul> <li>Surprisingly, it seems like the <code>drawInContext:</code> method always has the right value for <code>[self index]</code>, but it is not the method I want to use since I just set the <code>content</code> property with an image.</li> <li>I get different behaviors depending on the way I implement the <code>index</code> property. If I use <code>@dynamic index</code> (which works, even though the documentation doesn't say that custom property getters/setters would be dynamically implemented), <code>display</code> is called every time the value of <code>index</code> is changed. If I use <code>@synthesize</code> or implement a setter, <code>display</code> is not called, so I would need to change <code>content</code> in the setter too.</li> <li>Should I use an instance variable? Should I use the dynamic implementation? Or should I use <code>setValue:forKey:</code> instead?</li> </ul> <p>As you can see, I am a bit confused about how to get the result I want, and how to correctly implement a subclass of CALayer with a custom property. Any help, and explanations, would be appreciated!</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. CO"The documentation doesn't say that custom property getters/setters would be dynamically implemented" -- actually, this *is* documented in `CALayer.h`: "CALayer implements the standard NSKeyValueCoding protocol for all Objective C properties defined by the class and its subclasses. It dynamically implements missing accessor methods for properties declared by subclasses." So you do want to use `@dynamic` if you want `+needsDisplayForKey:` to work.
      singulars
    2. COGreat question… These "fundamental" questions are under-explained in the docs, and too esoteric for all-but-the-most-involved of how-to's. `CALayer`'s are such odd-balls.. I sort of think Apple regrets their implementation of them, or has too many competing technologies to bother with really documenting their often-mysterious behaviors.
      singulars
    3. COI agree... Core Animation is trivial to use for basic tasks, but if you try to dig deeper, it does become esoteric. Like the fact that layers have timing, in addition to animation timing. Or the mysterious `contents` property whose type is `id`, and which can contain a cached `CABackingStore`. Or the fact that `CATransition` inherits from `CAAnimation` yet works in a completely opaque way... Or even the relationship between `UIView` animation blocks and `CALayer` animation...
      singulars
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload