devbot10
devbot10

Reputation: 1253

Timer countdown in swift skipping seconds and pausing

I am making a countdown component to an app I am updating. I finally got it working but when it is on my simulator or when I run it through my phone, it bogs down and skips seconds, sometimes freezing my screen and not allowing me to change views and such. This is my code below. I am curious why this is happening.

Thank you in advance!

class CountdownViewController: UIViewController {

@IBOutlet weak var days: UILabel!
@IBOutlet weak var hours: UILabel!
@IBOutlet weak var minutes: UILabel!
@IBOutlet weak var seconds: UILabel!

var timer:NSTimer!

func reloadData(){
    self.viewDidLoad()
}

override func viewDidLoad() {
    super.viewDidLoad()

    self.timer = NSTimer(timeInterval: 0.5, target: self, selector: Selector("reloadData"), userInfo: nil, repeats: true)

    NSRunLoop.currentRunLoop().addTimer(self.timer, forMode: NSRunLoopCommonModes)

    self.canDisplayBannerAds = true

    // here we set the current date
    let date = NSDate()
    let calendar = NSCalendar.currentCalendar()
    let components = calendar.components(.CalendarUnitHour | .CalendarUnitMinute | .CalendarUnitMonth | .CalendarUnitYear | .CalendarUnitDay | .CalendarUnitSecond, fromDate: date)
    let hour = components.hour
    let minute = components.minute
    let month = components.month
    let year = components.year
    let day = components.day
    let second = components.second

    let currentDate = calendar.dateFromComponents(components)

    // here we set the due date. When the timer is supposed to finish

    let userCalendar = NSCalendar.currentCalendar()

    let electionDate = NSDateComponents()
    electionDate.year = 2016
    electionDate.month = 11
    electionDate.day = 08
    electionDate.hour = 00
    electionDate.minute = 00
    electionDate.second = 00
    let electionDay = userCalendar.dateFromComponents(electionDate)!


    // Here we compare the two dates
    electionDay.timeIntervalSinceDate(currentDate!)

    let dayCalendarUnit: NSCalendarUnit = (.CalendarUnitDay | .CalendarUnitHour | .CalendarUnitMinute | .CalendarUnitSecond)

    //here we change the seconds to hours,minutes and days
    let electionDayDifference = userCalendar.components(dayCalendarUnit, fromDate: currentDate!, toDate: electionDay,options: nil)

    //finally, here we set the variable to our remaining time
    var daysLeft = electionDayDifference.day
    var hoursLeft = electionDayDifference.hour
    var minutesLeft = electionDayDifference.minute
    var secondsLeft = electionDayDifference.second

    days.text = String(daysLeft)
    hours.text = String(hoursLeft)
    minutes.text = String(minutesLeft)
    seconds.text = String(secondsLeft)

}

Upvotes: 0

Views: 1106

Answers (2)

vadian
vadian

Reputation: 285059

Do not call viewDidLoad()

It's a kind of delegate method which is called (once) by the view controller and is designated for setting up things once.

Put your code to be executed after the timer fires in a custom function. It's not necessary to create the timer again and again, setting the parameter repeats to true calls the selector periodically.

Upvotes: 0

glyuck
glyuck

Reputation: 3397

You are adding more and more timers to RunLoop every 0.5 seconds. And they are all fired at once, causing performance degradation over time. You need to move all code below // here we set the current date comment to reloadData function and remove self.viewDidLoad() from there, and everything should be fine. Your timer will be scheduled only once and will call reloadData every 0.5 seconds repeatedly (because you created it with repeats: true parameter).

Upvotes: 3

Related Questions