代码之家  ›  专栏  ›  技术社区  ›  zpasternack

为什么我的CATransaction不尊重我设定的时间?

  •  4
  • zpasternack  · 技术社区  · 14 年前

    我正在将一个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:正在工作,因为动画完成时该块正在执行。

    我在这里做错什么了?

    2 回复  |  直到 14 年前
        1
  •  5
  •   SteamTrout    14 年前

    如果我没有弄错的话,你不能直接用CoreAnimation来制作NSView的动画。为此,您需要NSAnimationContext和[NSView animator]。CATransaction只适用于CALayers。

        2
  •  2
  •   zpasternack    14 年前

    - (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那样的回调完成机制,所以我不得不把它放在那里显式地获取视图的动画并设置委托,以便触发回调。问题是,每个动画都会被多次触发。结果证明这对我的所作所为没有不良影响,只是感觉不对。

    推荐文章