Swift - 何时或如何在视图开始时实现动画?

时间:2015-04-28 05:01:36

标签: ios swift animation

我是Swift的新手,我试图实现一个简单的游戏。在这个游戏中,一旦加载了视图,我希望定期动画发生。

问题在于我尝试使用button.frame.origin.x += 50设置按钮的动画,但不是将其从原点移动到50px,而是显示在button.frame.origin.x - 50并且去到(初始)位置。 有趣的是,我一度向用户显示AlertDialog,并在显示之后动画开始按照我的预期发生。

我的问题与this topic相同,但接受的答案并没有为我解决。

有什么想法吗?

修改 深入研究代码并测试很多我发现我显示AlertDialog的方法也会使我的计时器无效。我有两个计时器:一个用于更新UI时间(一个TextField),另一个用于执行动画。两者都在安排任务。从I read here开始,就不可能有两个这样的计时器。

  

一次只能在一个运行循环中注册一个计时器对象,   虽然它可以在该运行中添加到多个运行循环模式   循环。

因此,显而易见的解决方案是将两个选择器(函数)合并为一个,因此计时器将适用于这两个任务。但是,如果我尝试更新UI并执行动画,则动画不再按预期工作。我只是迷失在这个问题上,并不能使两件事都有效。

这些是我的重要代码:

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)
    ...

    resetOrCreateGame()
}

func resetOrCreateGame() {
    // Do stuff to initialize values
    timerToRotate = NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: "rotateBlocks", userInfo: nil, repeats: true)
}

func rotateBlocks() {
    // Calculate positions to rotate
    UIView.animateWithDuration(0.5, delay: 0, options: UIViewAnimationOptions.CurveEaseOut, animations: {
        // Try to update a timer in the UI
        //self.timeLeft.text = String(self.seconds)

        for i in 0 ... 8 {
            println("\(i) before \(self.buttons[i].frame.origin.x) \(self.buttons[i].frame.origin.y)")
            self.buttons[i].frame.origin.x = self.positions[self.indicesToRotate[i]].x
            self.buttons[i].frame.origin.y = self.positions[self.indicesToRotate[i]].y

            println("\(i) after \(self.buttons[i].frame.origin.x) \(self.buttons[i].frame.origin.y)")
        }
        }, completion: { _ in
                println("completed")
            })

如果我对self.timeLeft.text = String(self.seconds)行发表评论,则动画效果正常。无论我如何尝试更新timeLeft,如果我这样做,它会搞砸我的动画。我试图在一个单独的线程中更新它,将它发送到主线程,或者甚至在动画闭包内更新它:它只是不起作用。

2 个答案:

答案 0 :(得分:0)

尝试使用SKAction来制作动画。

设置SKAction,然后在要设置动画的SpriteKit node上(用节点的名称替换" node")并调用它action

然后,调用简单的方法:

[node runAction:action];

例如,如果您要设置SKAction以在3秒的时间内向右移动标题为button 50像素的节点...

SKAction *action = [SKAction moveByX:50.0 y:0.0 duration:3.0];
[button runAction:action];

哎呀,如果我不经常做一次动作,我只是这样做:

[button runAction:[SKAction moveByX:50.0 y:0.0 duration:3.0]];

最后,您可以使用runAction:completion:方法不仅可以运行SKAction,还可以在完成后调用Objective-C block,就像这样编码示例:

SKAction *action = [SKAction moveByX:50.0 y:0.0 duration:3.0];
[button runAction:action completion:^{
     // some code here that runs after an animation completes
}];

并且,如果要在节点上运行序列操作(在3秒内将按钮向右移动一个名为button的50个像素),则不要使代码复杂化淡出1秒以上),你可以将一系列动作编程为一个动作,如下所示:

SKAction *firstAction = [SKAction moveByX:50.0 y:0.0 duration:3.0];
SKAction *secondAction = [SKAction fadeAlphaTo:0.0 duration:1.0];
SKAction *theSequence = [SKAction sequence:[NSArray arrayWithObjects:firstAction, secondAction, nil];
[button runAction:theSequence]

您可以在completion块中运行其他操作,但使用sequence的方法可以清除代码。

答案 1 :(得分:0)

最后,我找到了解决方案! 出于某种原因的问题是自动布局。禁用后,一切按预期工作。

希望将来帮助某人!