Animate Frame Size in Cocoa plus notification on animation end - cocoa

At the moment i have this code:
[[myView animator] setFrameSize:NSMakeSize(300, 150)];
And at the end of the animation i need to launch other operations so i need to know about that.
On the otherside i read the the CAAnimation class has a delegate method that could be exactly what i'm looking for (animationDidStop:finished:), but i like to know it i can have the same effect using animator proxy o CABasicAnimation.

Related

CALayer -displayLayer:inContext: never called during frame/bounds animation

I need to animate the frame of a CALayer instance; during the animation I should also update/redraw the content of the layer based upon the new size (frame by frame) of it.
I've tried to watch and use -displayLayer:inContext: of CALayer (it's a delegate property) but It does not work: both with frame (it's a derived property of bounds/location/anchorPoint) and bounds animation I can't receive this message (it should be called by CALayer's internal drawInContext: method) during the animation process.
Using needsDisplayOnBoundsChange I can get it called at the end of the animation, but nothing with bounds.
It works fine with custom properties (I need to return YES on needsDisplayForKey method).
Any idea?
Is possible to force redraw of CALayer contents during bounds/frame animation?

Efficient drawing in NSView drawRect

I have an application I'm writing in which I'm drawing into an NSView. In mouseDown I am saving the location in my data model and then drawing a graphic at that location within the drawRect method of the view. It all works fine.
At the end of my mouseDown I was calling [self setNeedsDisplay:YES]; to force a redraw. The only thing is that the dirtyRect is always the full size of the view. I wanted to optimize this as much as possible so that I'm not redrawing the entire window for just a few changed pixels.
So now I'm calling [self drawRect:...] instead and specifying the rectangle.
Now in my drawRect I am comparing every graphic I have to see if it falls in the dirtyRect. It seems like I've traded work of drawing for work of bounds checking everything. I'm not sure I've made it any more or less efficient.
So what is the standard practice? Is it common to just redraw everything in the view and ignore the dirtyRect? Is there a nice function I can use as a test to see whether my object is in the dirtyRect?
You should never call -drawRect: yourself if you're trying to draw to the screen. Let AppKit call it for you. What you should do is call -setNeedsDisplayInRect: at the end of your -mouseDown:.
Then, in -drawRect:, only draw stuff contained in the dirtyRect. You can test to see if a point is inside the dirtyRect with NSPointInRect(). There are lots of other useful functions for working with NSRect. See the documentation for the point functions and the rectangle functions.

NSBezierPath point animation in NSView

I've built a custom control in Cocoa which is drawn using an NSBezierPath and I'd like it to change shape when it's state has changed (unused state = a pointed 'look here' edge, used state = standard control edge).
It feels like I've looked through every mention of "NSBezierPath" and "Animation" there is on the web but with no luck.
Before I crack out some NSTimers and write my own timing & path point controls, does anyone know if this is possible using Core Animation or similar?
You could use NSAnimation. Create your own NSAnimation subclass, and override setCurrentProgress method.
In that method, you can change your NSBezierPath size, shape or whatever you need, based on current animation progress. After that you can force a redraw in the view (via delegate, for instance) to re-display the path.

UIImageView/AVAudioPlayer synchronization

I have an UIView that possess an UIImageView as a subview. This image view is intended to display an animation (basically, with the startAnimating method). When the animation start, I also need to play a sound. For this purpose, I use AVAudioPlayer's prepareToPlay and play methods.
Problem I encounter is that the FIRST TIME the global animation (image animation itself + sound) is launched, the sound is systematically played before the image animation is actually started. Not weird at all considering there is no synchronisation whatsoever.
But how could this synchronization be achieved? Is there some sort of callback which could be used know when the image animation is playing and launch the sound play from there...
Or maybe coupling UIImageView and AVAudioPlayer is not a good idea at all?
Here is my current implementation :
- (void)playSample {
previewView_ = [[[PreviewView alloc] initWithFrame:topView.bounds
backgroundImages:backgroundAnimationImages
characterImages:characterAnimationImages] autorelease];
[previewView_ setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
[topView addSubview:previewView_];
[audioPlayer_ setDelegate:self];
[audioPlayer_ setVolume:1.0];
[previewView_ startPreview]; // This calls startAnimating on the UIImageView of previewView_
[audioPlayer_ playSound];
}
Maybe you could use:
[audioPlayer playAtTime:[audioPlayer
deviceCurrentTime] + someDelayTimeInterval]
I found the the audioPlayer (or prepareToPlay) was messing up with my display updates, so what I ended up doing was to create the audioPlayer for each sound in viewDidLoad: and play it in a method called in a background thread:
[self performSelectorInBackground:#selector(playAudioPlayer:)
withObject:self.audioPlayer];

how to know when a coreanimation animation ends

I'm doing some animations with core animation, but I can't found a way to know with a notification or event when the animation block has finish, like in UIVIew animation block you have
setAnimationDidStopSelector:
how can I know this in core animation, thanks for any help
If you are using a CAAnimation instance, look at the animationDidStop:finished: for its delegate.
CAAnimation * animation = [CAAnimation animation];
animation.delegate = yourDelegate; // could be self, for example.
[yourLayer setAnimation:animation forKey:nil];
In the example above, yourDelegate should implement the animationDidStop:finished: method to be able to detect the animation end.

Resources