Why Does Cabasicanimation Try to Initialize Another Instance of My Custom Calayer

CABasicAnimation creates empty default value copy of CALayer

Figured out the answer!

In init(layer:) you have to copy the property values to your class manually. Here's how that looks in action:

override init(layer: AnyObject) {
if let layer = layer as? RadialGradientLayer {
gradientOrigin = layer.gradientOrigin
gradientRadius = layer.gradientRadius
colors = layer.colors
locations = layer.locations
}
super.init(layer: layer)
}

Animating a custom property of CALayer subclass

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:.

Why would CALayer animation work after loading view, but not just after initialization?

Initialization is too early. You need to wait until the view is in your interface (signaled to the view by didMoveToWindow. Until then, the view is not part of the rendering tree (which is what does the drawing/animation of its layers).

CALayer initWithLayer: bound to default constructor by mistake? Can I override the default constructor?

I cannot find any equivalent binded method for CALayer's initWithLayer:(layer) selector that I can override.

Looking at the Monotouch Assembly, the selector initWithLayer is bound to the default constructor like so:

A little bit of terminology: public CALayer (CALayer other) isn't a default constructor - a default constructor doesn't have any parameters.

However I need to be able to override the initWithLayer in order to animate my custom property in my CALayer class. (As specified in my previous question Animate a custom property using CoreAnimation in Monotouch?)

That question doesn't say why you need to override the initWithLayer constructor. I did find this though: Why animating custom CALayer properties causes other properties to be nil during animation?, which seems to be what you're trying to do. In this case I think there is an easier way to accomplish your need: you just need to override the Clone method in your custom CALayer class, and do the proper initialization there.

Was this done by mistake, or am I incorrect in saying that it's not possible to override a default constructor?

Technically, in C# you don't override a constructor. In your base class you provide your own constructors, and all of them must call one constructor in the immediate base class (this may be done implicitly by the compiler in some cases).

That said, in MonoTouch you can provide a constructor in your class that does everything you want (I still believe you should try the Clone approach first though):

public MyCALayer : CALayer {
[Export ("initWithLayer:")]
public MyCALayer (CALayer other) : base (other)
{
// custom initialization here
}

public override void Clone ()
{
// copy any code that you care about here.
}
}

CABasicAnimation's call to drawInContext causes instance variables to reset to zero

When doing an animation, Core Animation makes a copy of the layer and assign's it to the layer's presentationLayer property. The animation is then executed on the presentationLayer. AFAIK only properties are copied, not ivars. Try declaring Foo as a property and see if that helps.

How is the presentation layer of a CALayer generated?

Override the initWithLayer: method.



Related Topics



Leave a reply



Submit