I was facing the struggle of making a timer app, so I thought that now that I solved it I could help others who face the problem. So basically this app counts down to a specific
This worked for me. The only thing that troubles me is that it doesn't really countdown as the user has to refresh the page for it to recount. You can see it "counting" when the user is scrolling up and down cells on a UITableView as the cells do refresh the view. Another thing is that I have on NSTimeZone of the currentDate "GMT+2:00" as it works for my time but only because I haven't figured out how to use the device NSTimeZone yet.
let releaseDate = "2015-05-02'T'22:00:00:000Z"
let futureDateFormatter = NSDateFormatter()
futureDateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
let date: NSDate = futureDateFormatter.dateFromString(releaseDate!)!
let currentDate = NSDate();
let currentFormatter = NSDateFormatter();
currentFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
currentFormatter.timeZone = NSTimeZone(abbreviation: "GMT+2:00")
let diffDateComponents = NSCalendar.currentCalendar().components([NSCalendarUnit.Month, NSCalendarUnit.Day, NSCalendarUnit.Hour, NSCalendarUnit.Minute], fromDate: currentDate, toDate: date, options: NSCalendarOptions.init(rawValue: 0))
let countdown = "\(diffDateComponents.month) m: \(diffDateComponents.day) d: \(diffDateComponents.hour) h: \(diffDateComponents.minute) min"
Cleaned up/updated for latest Swift version of the accepted answer.
// here we set the current date
let date = NSDate()
let calendar = Calendar.current
let components = calendar.dateComponents([.hour, .minute, .month, .year, .day], from: date as Date)
let currentDate = calendar.date(from: components)
let userCalendar = Calendar.current
// here we set the due date. When the timer is supposed to finish
let competitionDate = NSDateComponents()
competitionDate.year = 2017
competitionDate.month = 4
competitionDate.day = 16
competitionDate.hour = 00
competitionDate.minute = 00
let competitionDay = userCalendar.date(from: competitionDate as DateComponents)!
//here we change the seconds to hours,minutes and days
let CompetitionDayDifference = calendar.dateComponents([.day, .hour, .minute], from: currentDate!, to: competitionDay)
//finally, here we set the variable to our remaining time
let daysLeft = CompetitionDayDifference.day
let hoursLeft = CompetitionDayDifference.hour
let minutesLeft = CompetitionDayDifference.minute
print("day:", daysLeft ?? "N/A", "hour:", hoursLeft ?? "N/A", "minute:", minutesLeft ?? "N/A")
//Set countdown label text
countDownLabel.text = "\(daysLeft ?? 0) Days, \(hoursLeft ?? 0) Hours, \(minutesLeft ?? 0) Minutes"
Here is the solution of how I managed to create a countdown timer to a specific NSDate, for SO allows Q and A Style Answers.
// here we set the current date
let date = NSDate()
let calendar = NSCalendar.currentCalendar()
let components = calendar.components(.CalendarUnitHour | .CalendarUnitMinute | .CalendarUnitMonth | .CalendarUnitYear | .CalendarUnitDay, fromDate: date)
let hour = components.hour
let minutes = components.minute
let month = components.month
let year = components.year
let day = components.day
let currentDate = calendar.dateFromComponents(components)
// here we set the due date. When the timer is supposed to finish
let userCalendar = NSCalendar.currentCalendar()
let competitionDate = NSDateComponents()
competitionDate.year = 2015
competitionDate.month = 6
competitionDate.day = 21
competitionDate.hour = 08
competitionDate.minute = 00
let competitionDay = userCalendar.dateFromComponents(competitionDate)!
// Here we compare the two dates
competitionDay.timeIntervalSinceDate(currentDate!)
let dayCalendarUnit: NSCalendarUnit = (.CalendarUnitDay | .CalendarUnitHour | .CalendarUnitMinute)
//here we change the seconds to hours,minutes and days
let CompetitionDayDifference = userCalendar.components(
dayCalendarUnit, fromDate: currentDate!, toDate: competitionDay,
options: nil)
//finally, here we set the variable to our remaining time
var daysLeft = CompetitionDayDifference.day
var hoursLeft = CompetitionDayDifference.hour
var minutesLeft = CompetitionDayDifference.minute
Hope that helps you guys if you're facing the same struggle as I have
Cleaned up and updated with countdown computed on a timer and leading zero String format.
let futureDate: Date = {
var future = DateComponents(
year: 2020,
month: 1,
day: 1,
hour: 0,
minute: 0,
second: 0
)
return Calendar.current.date(from: future)!
}()
var countdown: DateComponents {
return Calendar.current.dateComponents([.day, .hour, .minute, .second], from: Date(), to: futureDate)
}
@objc func updateTime() {
let countdown = self.countdown //only compute once per call
let days = countdown.day!
let hours = countdown.hour!
let minutes = countdown.minute!
let seconds = countdown.second!
countdownLabel.text = String(format: "%02d:%02d:%02d:%02d", days, hours, minutes, seconds)
}
func runCountdown() {
Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true)
}