Colton White
Colton White

Reputation: 3

Creating a simple countdown to date in Swift 4

I'm working on a very simple app that counts down to a date. I found several tutorials but nothing in Swift 4. It seems like a lot has changed as I keep getting compiler errors.

Here is my code:

class ViewController: UIViewController {
    @IBOutlet weak var CountdownText: UILabel!

    let formatter = DateFormatter()
    let userCalendar = NSCalendar.current

    let requestedComponent: NSCalendar.Unit = [
        NSCalendar.Unit.month,
        NSCalendar.Unit.day,
        NSCalendar.Unit.hour,
        NSCalendar.Unit.minute,
        NSCalendar.Unit.second,
    ]

    func printTime()
    {
        formatter.dateFormat = "MM/dd/yy hh:mm:ss a"
        let startTime = NSDate()
        let endTime = formatter.date(from: "12/03/18 2:00:00 p")

        func timeDifference (requestedComponent: NSCalendar.Unit, from: startTime, to: endTime!, options: [NSCalendar.Options]) {}

        CountdownText.text = "\(timeDifference.day) Days \(timeDifference.minute) Minutes \(timeDifference.second) Seconds"
    }
}

My errors are:

Use of undeclared type 'startTime'
Use of undeclared type 'endTime'

Upvotes: 0

Views: 2734

Answers (2)

Thomas Easo
Thomas Easo

Reputation: 3758

How to use

  1. Copy the Code to your specific View Controller
  2. Change the value of variable dateString with your date in the format

Date Format "< Month > < date >, < year > < hour >:< minute >:< second >"

Ex. "March 4, 2018 13:20:10"

Code

The below code will be useful for achieving a countdown timer of your custom date.

//
//  DateCountDownTimer.swift
//  CountDownTimerLearning
//
//  Created by ThomasVEK on 04/03/18.
//  Copyright © 2018 TVEK Solutions. All rights reserved.
//

import Foundation



func defaultUpdateActionHandler(string:String)->(){

}

func defaultCompletionActionHandler()->(){

}

public class DateCountDownTimer{

    var countdownTimer: Timer!
    var totalTime = 60
    var dateString = "March 4, 2018 13:20:10" as String
    var UpdateActionHandler:(String)->() = defaultUpdateActionHandler
    var CompletionActionHandler:()->() = defaultCompletionActionHandler

    public init(){
        countdownTimer = Timer()
        totalTime = 60
        dateString = "March 4, 2018 13:20:10" as String
        UpdateActionHandler = defaultUpdateActionHandler
        CompletionActionHandler = defaultCompletionActionHandler
    }

    public func initializeTimer(pYear:Int, pMonth:String, pDay:Int, pHour:Int, pMin:Int, pSec:Int){

        self.dateString = "\(pMonth) \(pDay), \(pYear) \(pHour):\(pMin):\(pSec)" as String

        // Setting Today's Date
        let currentDate = Date()

        // Setting TargetDate
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "MM-dd-yyyy HH:mm:ss"
        dateFormatter.timeZone = NSTimeZone.local
        let targedDate = dateFormatter.date(from: dateString) as! Date

        // Calculating the difference of dates for timer
        let calendar = Calendar.current.dateComponents([.day, .hour, .minute, .second], from: currentDate, to: targedDate)
        let days = calendar.day!
        let hours = calendar.hour!
        let minutes = calendar.minute!
        let seconds = calendar.second!
        totalTime = hours * 60 * 60 + minutes * 60 + seconds
        totalTime = days * 60 * 60 * 24 + totalTime
    }

    func numberOfDaysInMonth(month:Int) -> Int{
        let dateComponents = DateComponents(year: 2015, month: 7)
        let calendar = Calendar.current
        let date = calendar.date(from: dateComponents)!

        let range = calendar.range(of: .day, in: .month, for: date)!
        let numDays = range.count
        print(numDays)
        return numDays
    }

    public func startTimer(pUpdateActionHandler:@escaping (String)->(),pCompletionActionHandler:@escaping ()->()) {
        countdownTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true)
        self.CompletionActionHandler = pCompletionActionHandler
        self.UpdateActionHandler = pUpdateActionHandler
    }

    @objc func updateTime() {
        self.UpdateActionHandler(timeFormatted(totalTime))

        if totalTime > 0 {
            totalTime -= 1
        } else {
            endTimer()
        }
    }

    func endTimer() {
        self.CompletionActionHandler()
        countdownTimer.invalidate()
    }

    func timeFormatted(_ totalSeconds: Int) -> String {
        let seconds: Int = totalSeconds % 60
        let minutes: Int = (totalSeconds / 60) % 60
        let hours: Int = (totalSeconds / 60 / 60) % 24
        let days: Int = (totalSeconds / 60 / 60 / 24)
        return String(format: "%dD %02dH %02dM %02dS", days, hours, minutes, seconds)
    }

}

Upvotes: 1

GrandFelix
GrandFelix

Reputation: 551

You have specified timeDifference function inside printTime() function and in timeDifference() function you have defined from and to parameters which ones types are startTime and endTime which ones are not types. Replace them with NSDate like:

func timeDifference (requestedComponent: NSCalendar.Unit, from: NSDate, to: NSDate, options: [NSCalendar.Options]) {}

and then call this function with startTime and ednTime variables that you have defined.

Also I think that you should define timeDifference function outside of printTime function.

Upvotes: 1

Related Questions