Search code examples
cocoansviewcore-imagecatransitionnsviewanimation

CATransition with CIFilter doesn't work first time,works second time


I want to add CATransition animation for NSView. I have the following code:

[contentView setWantsLayer:YES];
NSRect rect = [contentView bounds];

NSData *shadingBitmapData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"restrictedshine" ofType:@"tiff"]]; // took from Apple's example
NSBitmapImageRep *shadingBitmap = [[[NSBitmapImageRep alloc] initWithData:shadingBitmapData] autorelease];
CIImage *inputShadingImage = [[[CIImage alloc] initWithBitmapImageRep:shadingBitmap] autorelease];
CIFilter *transitionFilter = [CIFilter filterWithName:@"CIRippleTransition"];
[transitionFilter setDefaults];
[transitionFilter setValue:[CIVector vectorWithX:NSMidX(rect) Y:NSMidY(rect)] forKey:@"inputCenter"];
[transitionFilter setValue:[CIVector vectorWithX:rect.origin.x Y:rect.origin.y Z:rect.size.width W:rect.size.height] forKey:@"inputExtent"];
[transitionFilter setValue:inputShadingImage forKey:@"inputShadingImage"];

CATransition *presentAnimation = [CATransition animation];
[presentAnimation setFilter:transitionFilter];
[presentAnimation setDuration:1.0];
[presentAnimation setDelegate:self];

[contentView setAnimations:[NSDictionary dictionaryWithObject:presentAnimation forKey:@"subviews"]];
// maybe there are memory leaks in this code, don't bother at this moment

The problem is:

  1. I execute this code.

  2. I do [[contentView animator] addSubview:mySubview]; for the first time, it does not work. View just appears. CATransition delegate methods are called, but finished flag is NO (false).

  3. I remove view by [mySubview removeFromSuperview]; and it removes with animation, finished flag = YES (true).

  4. I repeat steps 2 and 3 and it works with animation. Step 2 now tells that animation was finished (YES). Works as expected.

What's wrong?


Solution

  • Problem resolved.

    First of all: [contentView setWantsLayer:YES];, and this must be set before performing animations. Better place for this are awakeFromNib or init methods, or something like this. You need to enable Core Animation on contentView, perform UI drawing (I mean allow your app to do this), and only then perform animations. In my case I enabled Core Animation and performed animation immediately, and that's why it did not work for me.