5

我正在将 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: 调用在做任何事情。但是, setCompletionBlock: 正在工作,因为该块在动画完成时正在执行。

我在这里做错了什么?

4

2 回答 2

5

如果我没记错的话,你不能使用 CoreAnimation 直接为 NSView 设置动画。为此,您需要 NSAnimationContext 和 [NSView animator]。CATransaction 仅适用于 CALayers。

于 2010-11-09T07:43:49.653 回答
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 那样的回调完成机制,所以我必须把东西放在那里显式地获取视图的动画并设置委托以便触发回调。问题在于,每个动画都会多次触发它。事实证明,这对我正在做的事情没有任何不良影响,只是感觉不对。

这是可行的,但如果有人知道更好的解决方案,我仍然想要一个。

于 2010-11-09T07:19:42.590 回答