I am building a tiny stopwatch app. It consists of a main view with a label displaying the time and two buttons: start & stop.
The start button activates NSTimers
which then call methods that calculate the time passed and then update the labels accordingly. The stop button simply invalidates the timers.
On the upper right hand corner, there is an arrow button that is supposed to move all the UI elements to the left and show a menu. That works great when the timers and not running and thereby the labels are not being updated.
However, when running the timers & thereby updating the labels simultaneously, shortly after beginning the animation, everything snaps back to the position it was in previously. When invalidating the timers with the stop button, the animation is working fine again.
Animation in toggleMenu()
UIView.animateWithDuration(0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0.5, options: .CurveEaseOut, animations: {
if self.arrow.frame.origin.x >= screenBounds.width/2 {
//if menu is NOT visible (mainView ON-SCREEN, menu right)
for element in self.UIElements {element.frame.origin.x -= screenBounds.width}
self.arrow.frame.origin.x = 0
self.arrow.transform = CGAffineTransformMakeRotation(CGFloat(-M_PI))
} else {
//if menu IS visible (mainView left, menu ON-SCREEN)
for element in self.UIElements {element.frame.origin.x += screenBounds.width}
self.arrow.frame.origin.x = screenBounds.width-self.arrow.frame.width
self.arrow.transform = CGAffineTransformMakeRotation(CGFloat(0))
}
}, completion: nil)
Updating Labels in timer-called updateTime()
let currentTime = NSDate.timeIntervalSinceReferenceDate()
var elapsedTime: NSTimeInterval = currentTime - startTime
let hrs = UInt8(elapsedTime/3600)
elapsedTime -= NSTimeInterval(hrs)*3600
let mins = UInt8(elapsedTime/60)
elapsedTime -= NSTimeInterval(mins)*60
let secs = UInt8(elapsedTime)
elapsedTime -= NSTimeInterval(secs)
let strHrs = String(format: "%02d", hrs)
let strMins = String(format: "%02d", mins)
let strSecs = String(format: "%02d", secs)
//update time labels
self.time.text = "\(strHrs):\(strMins)"
self.secs.text = "\(strSecs)"
With no luck, I tried...
clipsToBounds
set true)I figured...
Any thoughts?
Thanks in advance!
When you update the labels, Auto Layout is running and placing your UI elements back to where their constraints say they should be. You shouldn't alter the frames of objects that are under the control of Auto Layout or you will get unexpected results.
Instead of updating the origin.x
of your UI elements, create @IBOutlet
s to the NSLayoutContraints
that position them horizontally and then update the constant
property of the constraints and call self.view.layoutIfNeeded()
in your animation loop.
It might be easier to make all of your UI elements be a subview of a top level UIView, and then you'd only need to update the one constraint that places that UIView horizontally to move it offscreen.