iOS/iPhone/iPad/watchOS/tvOS/MacOSX/Android プログラミング, Objective-C, Cocoa, Swiftなど
自分自身への冬休みの宿題として、Core Animationを課題としてあげる事にした。
宿題に取り組む前は、上記教科書の章立てについて疑問があったが、よくよく、読んでみると、関係性に気がついたので、それを説明してみることにした。
OS X限定となってしまうが、AppKitには、NSAnimatablePropertyContainerプトロコルを利用した、UIのアニメーション機能がある。このプロトコルの定義は以下のとおり。
使用方法は、以下のとおり。
マウス・クリックされると画像の位置が変化するプログラムの例だ。
@interface BaseView ()
@property (strong, nonatomic) NSImageView *mover;
@property (assign, nonatomic) NSRect leftFramePosiotion;
@property (assign, nonatomic) NSRect rightFramePosiotion;
@property (assign, nonatomic) BOOL isRight;
- (void)initializeFramePositions;
- (void)addImageToSubview;
- (void)move;
@end
@implementation BaseView
@synthesize mover = _mover;
@synthesize leftFramePosiotion = _leftFramePosiotion;
@synthesize rightFramePosiotion = _rightFramePosiotion;
@synthesize isRight = _isRight;
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self initializeFramePositions];
[self addImageToSubview];
[self addSubview:self.mover];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
[self initializeFramePositions];
[self addImageToSubview];
[self addSubview:self.mover];
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect
{
}
- (BOOL)acceptsFirstResponder
{
return YES;
}
- (void)mouseDown:(NSEvent*)theEvent
{
[self move];
}
- (void)initializeFramePositions
{
CGFloat frameX = NSWidth(self.frame);
CGFloat frameY = NSHeight(self.frame);
self.leftFramePosiotion = NSMakeRect(0.0, 0.0, frameX / 4.0, frameY / 4.0);
self.rightFramePosiotion = NSMakeRect(7.0 * frameX / 8.0, 7.0 * frameY / 16.0, frameX / 8.0, frameY / 8.0);
self.mover = [[NSImageView alloc] initWithFrame:self.leftFramePosiotion];
self.isRight = NO;
}
- (void)addImageToSubview
{
[self.mover setImageScaling:NSScaleToFit];
[self.mover setImage:[NSImage imageNamed:@"snapshot.jpg"]];
}
- (void)move
{
if (self.isRight) {
[self.mover setFrame:self.leftFramePosiotion];
}
else {
[self.mover setFrame:self.rightFramePosiotion];
}
self.isRight = !self.isRight;
}
@end
setFrame:メソッドで画像の位置が変わるのだが、これにAnimatorプロキシを加えると、アニメーションするようになる。変更するのは、moveメソッドだ。
- (void)move
{
if (self.isRight) {
[[self.mover animator] setFrame:self.leftFramePosiotion];
}
else {
[[self.mover animator] setFrame:self.rightFramePosiotion];
}
self.isRight = !self.isRight;
}
何が発生したのか説明すると、setFrame:でプロパティに対して変更が発生すると、それを契機にアニメーションしだす。プロパティ名をキーにしてanimationForKey:で利用するアニメーションを取得する。キーに対応した値は、valueForKey:で取得する。キーに対応するアニメーションが見つからない場合で、defaultAnimationForKey:でデフォルトのアニメーションを取得する。それでも見つからない場合はアニメーションしない。
次回からは、このとおりに動作していることを、要素毎に試行錯誤して確認してみようと思っている。