5

I've written some of this in pseudo code because I don't know the syntax for it. I'd like to have the timeLeftLabel.text reflect how many hours, minutes, and seconds are left until the 6 hours are up. My biggest problem is that I don't know how to add and subtract times. Can anyone help me?

var timer = NSTimer()

func timerResults() {
    let theDate = NSDate()
    var endTime = theDate //+ 6 hours
    let timeLeft = endTime //- theDate
    timeLeftLabel.text = "\(timeLeft)"
}

@IBOutlet weak var timeLeftLabel: UILabel!
@IBAction func IBbtnUpdateTap(sender: UIButton){

timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: Selector("timerResults"), userInfo: nil, repeats: true)

}
Victor Sigler
  • 23,243
  • 14
  • 88
  • 105
adman
  • 408
  • 1
  • 4
  • 21

2 Answers2

5

Assuming your deployment target is iOS 8.0 or later, you should use NSDateComponentsFormatter to format your string. You want something like this:

class MyViewController : UIViewController {

    @IBOutlet weak var timeLeftLabel: UILabel!

    var targetDate: NSDate?
    var labelUpdateTimer: NSTimer?
    var timeLeftFormatter: NSDateComponentsFormatter?

    @IBAction func startTimerButtonWasTapped() {
        targetDate = NSDate(timeIntervalSinceNow: 6 * 60 * 60)
        labelUpdateTimer = NSTimer.scheduledTimerWithTimeInterval(1,
            target: self, selector: "labelUpdateTimerDidFire:", userInfo: nil, repeats: true)
        timeLeftFormatter = NSDateComponentsFormatter()
        timeLeftFormatter?.unitsStyle = .Abbreviated // gives e.g. "1h 20m 34s"
            // You might prefer .Positional, which gives e.g. "1:20:34"
        timeLeftFormatter?.allowedUnits = [ .Hour, .Minute, .Second ]

        labelUpdateTimerDidFire(labelUpdateTimer!)
    }

    @objc func labelUpdateTimerDidFire(timer: NSTimer) {
        let now = NSDate()
        timeLeftLabel.text = timeLeftFormatter!.stringFromDate(now,
            toDate: targetDate!)
        if now.compare(targetDate!) != NSComparisonResult.OrderedAscending {
            print("times up!")
            labelUpdateTimer?.invalidate()
        }
    }

}
rob mayoff
  • 375,296
  • 67
  • 796
  • 848
  • What is the purpose in your code of the `@objc` keyword? There is some specific goal or something else? – Victor Sigler Nov 04 '15 at 00:04
  • It's not required in this case but it's habitual. – rob mayoff Nov 04 '15 at 01:16
  • @rob It's not quite working for me. When I press my button, my text reads "5h 59m 58s" and stays like that instead of counting down. Any suggestions? – adman Nov 04 '15 at 19:48
  • I've fixed my answer. Change `OrderedDescending` to `OrderedAscending` in `labelUpdateTimerDidFire(_:)`. Also, add a call to `labelUpdateTimerDidFire(_:)` at the end of `startTimerButtonWasTapped` so the label updates immediately when the timer starts. – rob mayoff Nov 04 '15 at 20:15
  • Rob Mayoff, you won the internet. – adman Nov 06 '15 at 06:34
3

This will add 6 hours:

let future = now.dateByAddingTimeInterval(3600*6) // 1 hour is 3600 seconds

This will find the difference:

let difference = future.timeIntervalSinceDate(now)
Aidan Gomez
  • 8,167
  • 5
  • 28
  • 51
  • Never do the first line. Not all hours have 3600 seconds. However, the 2nd line is correct for finding the number of seconds between the two dates. – rmaddy Nov 03 '15 at 23:40
  • @rmaddy wow, I never heard about hours which do not have 3600 seconds. Can you provide some more info about these? – Andriy Gordiychuk Nov 03 '15 at 23:45
  • @rmaddy I'll update with an NSDateComponents if he wants a meticulously correct answer. – Aidan Gomez Nov 03 '15 at 23:45
  • @AndriyGordiychuk Leap seconds happen once in a while and hours can be repeated or skipped twice a year during day light savings transitions. – rmaddy Nov 03 '15 at 23:46
  • @rmaddy: Leap seconds are not counted in the Unix time, so actually an hour always has 3600 seconds (as far as I know). But you are right of course that a day does not always has 24 hours. – Martin R Nov 04 '15 at 02:17