views:

585

answers:

1

I have a CALayer subclass, MyLayer, that has a NSInteger property called myInt. I'd really like to animate this property via CABasicAnimation, but it seems CABasicAnimation only works on so-called "animatable" properties (bounds, position, etc). Is there something I can override to make my custom myInt property animatable?

+10  A: 

Yes, it's possible (only in the latest Core Animation releases though, I believe, i.e. iPhone 3.0+ and OS X 10.6+).

  1. Make your property dynamic so that CA implements the accessors for you:

    @dynamic myInt;
    
  2. Tell the layer that changes of the property require redrawing:

    + (BOOL)needsDisplayForKey:(NSString*)key {
        if ([key isEqualToString:@"myInt"]) {
            return YES;
        } else {
            return [super needsDisplayForKey:key];
        }
    }
    
  3. Use the value of myInt in your drawInContext: method. Now, when you animate myInt, Core Animation will interpolate the values for each step of the animation and repeatedly ask the layer to draw itself.

  4. If you also want to enable implicit animations for this property, also override actionForKey:.

Ole Begemann
Thank you! This has me so close to a solution I can taste it! -drawInContext: is called several times with myInt interpolated correctly. Unfortunately CGContextDrawImage() no longer functions while the animation is running. Rects I fill or paths I stroke are all drawn correctly, but the image normally drawn by CGContextDrawImage() just disappears until the animation is over as if CGContextDrawImage() is never called. I'm baffled. Any thoughts?
jemmons
No idea, sorry. I hope you find a solution.
Ole Begemann
That's ok. You're reply is still one of the best written answers I've seen on Stack Overflow :)
jemmons
Dear future googlers: CGContextDrawImage() wasn't drawing because I was storing its CGImageRef in an ivar. When CoreAnimation spawns off its multiple presentation layers (or whatever) it doesn't copy ivars, only KVC values. Storing my image in a UIImage and then [self setValue:myUIImage forKey:@"image"] for later retrieval in -drawInContext: did the trick.
jemmons