6

I'm creating a countdown timer that counts down to an NSDate set in a UIDatePicker. I have a label that shows the date we're counting down to and that works fine.

What I'm also trying to add is labels for the number of whole days left and number of hours/minutes/seconds left in the current day (i.e. never more than 23/59/59) Here's what I've done at the minute but it obviously shows the values for the whole countdown. Hoping someone can help me work out the correct logic here.

let secondsLeft = sender.date.timeIntervalSinceDate(NSDate())
hoursLabel.text = String(secondsLeft % 3600)
minutesLabel.text = String((secondsLeft / 60) % 60)
secondsLabel.text = String(secondsLeft % 60)

I guess what I'm looking for is some swift equivalent of the datetime class you get in php

Chris Byatt
  • 3,689
  • 3
  • 34
  • 61

4 Answers4

10

Got it - for Swift 2

let calendar = NSCalendar.currentCalendar()
let components = calendar.components([.Day, .Hour, .Minute, .Second], fromDate: NSDate(), toDate: sender.date, options: [])
daysLabel.text = String(components.day)
hoursLabel.text = String(components.hour)
minutesLabel.text = String(components.minute)
secondsLabel.text = String(components.second)
Chris Byatt
  • 3,689
  • 3
  • 34
  • 61
2

Take a look at the NSCalendar class. Specifically look at the method components:fromDate:toDate:options: That lets you take 2 dates and calculate the difference between them using whatever units you specify.

It's also localizable, so if you use the current calendar and the user uses the Chinese, Hebrew, or Arabic calendar then the calculations will give you results correct for that calendar.

Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • Thanks - I just found this. Much easier! Although not much documentation on how to use it in swift 2 but I got it. – Chris Byatt Oct 13 '15 at 22:41
  • I feel sorry for people who started developing for iOS/Mac and only learned Swift. So much documentation/sample code is written in Objective-C it must be hard. (I'm bilingual, although probably stronger in Objective-C since I've been doing it since like 2006 or 2007. Love Swift though.) – Duncan C Oct 13 '15 at 23:26
  • I learnt very very basic obj-c then swift came out. The thing is in obj-c you'd fill the components part with `NSHour... | NSMinute.....` but that doesn't fly in swift which is where I got stuck trying to put this in... But only for a minute ;) – Chris Byatt Oct 13 '15 at 23:30
  • I love the new set notation support for enums. Much cleaner than bitwise math. (Although I kind of wish they supported that for old C hands like me. You have to use about 500 lbs. of type-casts between enums and their raw values to get that to work in Swift 2.0) – Duncan C Oct 13 '15 at 23:37
1

Here's a Swift 4 version of Chris Byatt's answer that is also playground-friendly:

import UIKit

let calendar = Calendar.current
let now = Date()
let futureDate = Date.distantFuture

let components = calendar.dateComponents([.day, .hour, .minute, .second], from: now, to: futureDate)

let daysLabel = UILabel()
let hoursLabel = UILabel()
let minutesLabel = UILabel()
let secondsLabel = UILabel()

daysLabel.text = String(describing: components.day)
hoursLabel.text = String(describing: components.hour)
minutesLabel.text = String(describing: components.minute)
secondsLabel.text = String(describing: components.second)

print(components) // day: 723942 hour: 23 minute: 56 second: 0 isLeapMonth: false

// Bonus: here's an easy way to print grammatically correct labels based on numbers
if let seconds = components.second {
    let labelText = "\(seconds) \(seconds == 1 ? "second" : "seconds")"
    print(labelText) // 0 seconds, 1 second, 2 seconds, etc.
}
Scott Gardner
  • 8,603
  • 1
  • 44
  • 36
1

Only Copy and Paste this code :

 @IBOutlet var countDownLabel: UILabel!


var count = 10800

override func viewDidLoad() {
    super.viewDidLoad()
    
    var timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(update), userInfo: nil, repeats: true)
}

func timeString(time: TimeInterval) -> String {
    let hours = Int(time) / 3600
    let minutes = Int(time) / 60 % 60
    let seconds = Int(time) % 60
    return String(format:"%02i:%02i:%02i", hours, minutes, seconds)
}

    @objc func update() {
       
        let time = timeString(time: TimeInterval(count))
        count = count - 1
        countDownLabel.text = time

    }

enter image description here

M Hamayun zeb
  • 448
  • 4
  • 10