i'm new swift , i'm trying implement simple game. in game, once view loaded want periodic animations happen.
the problem try animate buttons with, instance, button.frame.origin.x += 50
, instead of moving origin 50px right, appears @ button.frame.origin.x - 50 , goes (initial) position. funnily enough, @ 1 point show alertdialog
user, , after shown animation starts happen expected.
my problem same of this topic, accepted answer didn't solve me.
any thoughts?
edit: digging code , testing lot found out method show alertdialog happens invalidate timer. have 2 timers: 1 update ui time (a textfield), , other perform animation. both scheduling task. i read here, not possible have 2 timers that.
a timer object can registered in 1 run loop @ time, although can added multiple run loop modes within run loop.
hence, obvious solution merge 2 selectors (functions) one, timer work both tasks. however, if try update ui , perform animations, animations don't work expected anymore. i'm lost on problem , can't make both things work.
these important pieces of code:
override func viewdidappear(animated: bool) { super.viewdidappear(animated) ... resetorcreategame() } func resetorcreategame() { // stuff initialize values timertorotate = nstimer.scheduledtimerwithtimeinterval(2.0, target: self, selector: "rotateblocks", userinfo: nil, repeats: true) } func rotateblocks() { // calculate positions rotate uiview.animatewithduration(0.5, delay: 0, options: uiviewanimationoptions.curveeaseout, animations: { // try update timer in ui //self.timeleft.text = string(self.seconds) 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 leave line self.timeleft.text = string(self.seconds)
commented, animations work fine. no matter how try update timeleft, if screws animations. tried update in separate thread, dispatch main thread, or update inside animations closure: doesn't work.
try using skaction
s animate.
set skaction
, on spritekit node
want animate (replace "node
" name of node), , call action
.
then, call simple method:
[node runaction:action];
for example, if want set skaction
move node titled button
50 pixels right on timespan of 3 seconds...
skaction *action = [skaction movebyx:50.0 y:0.0 duration:3.0]; [button runaction:action];
heck, if don't run action more once, i'd this:
[button runaction:[skaction movebyx:50.0 y:0.0 duration:3.0]];
and finally, can use runaction:completion:
method not run skaction
, call objective-c block
after it's finished, in coding example:
skaction *action = [skaction movebyx:50.0 y:0.0 duration:3.0]; [button runaction:action completion:^{ // code here runs after animation completes }];
and, non-complicate code if want run sequence of actions on node (move button 50 pixels right called button
on 3 seconds, fade out on 1 second), can program sequence of actions 1 action, so:
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 run action in completion
block, method of using sequence
cleans code.