Learn Objective-C on the Mac - Mark Dalrymple [141]
This simple action method just calculates a new random location for sender within its superview and moves it there. Open MainMenu.xib in Interface Builder, put a button called Move in the empty window, and connect it to the app delegate’s move: action. Save your changes, Build & Run your project, and see that each time you click the Move button it hops to another location in the window.
Now, let’s animate the movement. We just need to edit a single line, changing this:
to this:
Build & Run, click the Move button, and see what happens. Now, each time you click the button, it slides smoothly into the new location instead of just switching instantaneously. The object returned by the animator method is a proxy that responds to each of NSView’s setter methods, and schedules animations to apply the change gradually. Behind the scenes, Core Animation does all the work of modifying the relevant value bit by bit until it reaches the target value specified in the call to the setter.
Each thread maintains an animation context, in the form of an instance of NSAnimationContext, which among other things lets you set the length of time (in seconds) that an implicit animation will take by first setting a value like this:
If that’s all the control you need over your animations, then you can get pretty far using implicit animations. If you need more fine-tuning, such as being able to ensure that several animations occur in a synchronized manner, or trigger some activity when an animation completes, then you’ll need something more, such as...
Explicit Animations
Core Animation provides a technique for setting up animations explicitly in your code, instead of using the “magic” of NSView’s animator method. Each animation you create explicitly is framed by methods that start and stop a section of animation code, making everything a little clearer. Combined with the added capabilities that explicit animations have, it’s clear that this is the right approach for all but the simplest of animations.
In order to use Core Animation, you first have to add the QuartzCore framework to your Xcode project. In Xcode, navigate to the Frameworks group, right-click on it, and choose Add➤Existing Frameworks... from the contextual menu that appears. Then, at the top of MovingButton_AppDelegate.m, add the following line:
Now you’re ready to refer to Core Animation classes in your own code. Let’s start by modifying the previous example to use explicit animation instead of implicit. To do this, we have to create an instance of a Core Animation class called CABasicAnimation, which is capable of animating between values for any CALayer property which can be animated. In our case, rather than animating the frame, we’ll animate the layer’s position property. We explicitly set start and end locations for the position using the animation’s toValue and fromValue properties. Note that these properties expect a proper object, not just a struct like NSPoint, so we have to wrap each NSPoint value inside an NSValue instance. After creating the animation we add it to the view’s layer, along with a key. This key doesn’t have anything to do with the property we’re animating, it’s only there to help us in case we later want to identify this animation. Finally, we change the frame on the view object itself, since the animation only affects the drawing of the view’s layer. We want the view to actually move as well, so we have to set its target frame manually. Here’s the code to do all of this:
Note that we also removed the [[sender animator] setFrame:senderFrame]; line from this method, because we don’t want to trigger an implicit animation this time. Before this will work, we need to do one more step that the implicit animations took care of for us: establishing