Swift - when or how to implement animation when viewing?

I am new to Swift and I am trying to implement a simple game. In this game, after loading the view, I want periodic animations to occur.

The problem is that I am trying to animate my buttons, for example, button.frame.origin.x += 50 , but instead of moving it from the origin to 50 pixels to the right, it appears on button.frame.origin.x - 50 and goes to its (initial) position. Oddly enough, at some point I show the user AlertDialog , and after showing it, the animation starts to happen as I expected.

My problem is the same in this section , but the accepted answer just didn't solve it for me.

Any thoughts?

Edit: Digging in the code and testing a lot, I found that the method in which I show AlertDialog also invalidates my timer. I have two timers: one for updating the user interface time (TextField), and the other for animation. Both are planning a task. What I'm reading from here is not possible to have two timers.

A timer object can only be registered in one run cycle at a time, although it can be added to several run cycle modes during this run cycle.

Therefore, the obvious solution would be to combine the two selectors (functions) into one, so the timer will work for both tasks. However, if I try to update the interface and perform the animation, the animations will not work as expected. I just lost this problem and cannot make both things work.

These are my important code snippets:

 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") }) 

If you leave the line self.timeLeft.text = String(self.seconds) commented, the animations will work fine. No matter how I try to update timeLeft, if I do, it spins my animations. I tried updating it in a separate thread, sending it to the main thread, or even updating it inside the closing animation: it just doesn't work.

0
ios animation swift
Apr 28 '15 at 5:01
source share
2 answers

Finally, I found a solution! The problem for some reason was auto-layout. After turning it off, everything worked as expected.

Hope this helps someone in the future!

0
Apr 30 '15 at 0:10
source share

Try using SKAction for animation.

Set up SKAction , then on the SpriteKit node you want to animate (replace " node " with the name node) and name it action .

Then call a simple method:

[node runAction:action];

For example, if you want to configure SKAction to move a node called button 50 pixels to the right for 3 seconds ...

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

If I had not run the action more than once, I would simply have done this:

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

And finally, you can use the runAction:completion: method not only to start SKAction , but also to call Objective-C block after it is completed, as in this encoding example:

 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 }]; 

And, in order not to complicate your code, if you want to run the sequence of actions on the node (move the button 50 pixels to the right, calling it button for 3 seconds, then fade it out for 1 second), you can program the sequence of actions in one action, for example:

 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] 

You can perform another action in the completion block, but the method of using sequence clears the code.

0
Apr 28 '15 at 5:15
source share



All Articles