我正在将iPhone应用程序移植到Mac OS X.此代码已在iPhone上成功使用:
- (void) moveTiles:(NSArray*)tilesToMove {
[UIView beginAnimations:@"tileMovement" context:nil];
[UIView setAnimationDuration:0.1];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(tilesStoppedMoving:finished:context:)];
for( NSNumber* aNumber in tilesToMove ) {
int tileNumber = [aNumber intValue];
UIView* aView = [self viewWithTag:tileNumber];
aView.frame = [self makeRectForTile:tileNumber];
}
[UIView commitAnimations];
}
Mac版本使用CATransaction对动画进行分组,如下所示:
- (void) moveTiles:(NSArray*)tilesToMove {
[CATransaction begin];
[CATransaction setAnimationDuration:0.1];
[CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[CATransaction setCompletionBlock:^{
[gameDelegate tilesMoved];
}];
for( NSNumber* aNumber in tilesToMove ) {
int tileNumber = [aNumber intValue];
NSView* aView = [self viewWithTag:tileNumber];
[[aView animator] setFrame:[self makeRectForTile:tileNumber]];
}
[CATransaction commit];
}
动画执行正常,但持续时间为1.0秒。我可以更改setAnimationDuration:调用任何东西,或者完全省略它,并且每次动画的持续时间仍为1.0秒。我也不认为setAnimationTimingFunction:call正在做任何事情。但是,setCompletionBlock:正在运行,因为动画完成时该块正在执行。
我在这里做错了什么?
答案 0 :(得分:5)
如果我没有弄错,你不能直接使用CoreAnimation来动画NSView。为此你需要NSAnimationContext和[NSView animator]。 CATransaction仅适用于CALayers。
答案 1 :(得分:2)
它没有完全回答这个问题,但我最终使用了NSAnimationContext而不是CATransaction。
- (void) moveTiles:(NSArray*)tilesToMove {
[NSAnimationContext beginGrouping];
[[NSAnimationContext currentContext] setDuration:0.1f];
for( NSNumber* aNumber in tilesToMove ) {
int tileNumber = [aNumber intValue];
NSView* aView = [self viewWithTag:tileNumber];
[[aView animator] setFrame:[self makeRectForTile:tileNumber]];
CAAnimation *animation = [aView animationForKey:@"frameOrigin"];
animation.delegate = self;
}
[NSAnimationContext endGrouping];
}
这是有效的,但我对此并不十分满意。主要是,NSAnimationContext没有像CATransaction那样的回调完成机制,所以我不得不把事情放在那里显式获取视图的动画并设置委托以便触发回调。问题是,每个动画都会多次触发它。事实证明,这对我正在做的事情没有任何不良影响,只是感觉不对。
这是可行的,但如果有人知道更好的解决方案,我仍然会喜欢。