[xcode] How can I make a countdown with NSTimer?

How can I make a countdown with an NSTimer using Swift?

This question is related to xcode swift nstimer

The answer is


Make Countdown app Xcode 8.1, Swift 3

import UIKit
import Foundation

class ViewController: UIViewController, UITextFieldDelegate {

    var timerCount = 0
    var timerRunning = false

    @IBOutlet weak var timerLabel: UILabel! //ADD Label
    @IBOutlet weak var textField: UITextField! //Add TextField /Enter any number to Countdown

    override func viewDidLoad() {
        super.viewDidLoad()

        //Reset
        timerLabel.text = ""
        if timerCount == 0 {
            timerRunning = false
        }
}

       //Figure out Count method
    func Counting() {
        if timerCount > 0 {
        timerLabel.text = "\(timerCount)"
            timerCount -= 1
        } else {
            timerLabel.text = "GO!"

        }

    }

    //ADD Action Button
    @IBAction func startButton(sender: UIButton) {

        //Figure out timer
        if timerRunning == false {
         _ = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(ViewController.Counting), userInfo: nil, repeats: true)
            timerRunning = true
        }

        //unwrap textField and Display result
        if let countebleNumber = Int(textField.text!) {
            timerCount = countebleNumber
            textField.text = "" //Clean Up TextField
        } else {
            timerCount = 3 //Defoult Number to Countdown if TextField is nil
            textField.text = "" //Clean Up TextField
        }

    }

    //Dismiss keyboard
    func keyboardDismiss() {
        textField.resignFirstResponder()
    }

    //ADD Gesture Recignizer to Dismiss keyboard then view tapped
    @IBAction func viewTapped(_ sender: AnyObject) {
        keyboardDismiss()
    }

    //Dismiss keyboard using Return Key (Done) Button
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        keyboardDismiss()

        return true
    }

}

https://github.com/nikae/CountDown-


Swift 4.1 and Swift 5. The updatetime method will called after every second and seconds will display on UIlabel.

     var timer: Timer?
     var totalTime = 60
    
     private func startOtpTimer() {
            self.totalTime = 60
            self.timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateTimer), userInfo: nil, repeats: true)
        }
    
    @objc func updateTimer() {
            print(self.totalTime)
            self.lblTimer.text = self.timeFormatted(self.totalTime) // will show timer
            if totalTime != 0 {
                totalTime -= 1  // decrease counter timer
            } else {
                if let timer = self.timer { 
                    timer.invalidate()
                    self.timer = nil
                }
            }
        }
    func timeFormatted(_ totalSeconds: Int) -> String {
        let seconds: Int = totalSeconds % 60
        let minutes: Int = (totalSeconds / 60) % 60
        return String(format: "%02d:%02d", minutes, seconds)
    }

XCode 10 with Swift 4.2

import UIKit

class ViewController: UIViewController {

   var timer = Timer()
   var totalSecond = 10

   override func viewDidLoad() {
       super.viewDidLoad()
       startTimer()
   }


   func startTimer() {
       timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true)
   }

   @objc func updateTime() {

        print(timeFormatted(totalSecond))

        if totalSecond != 0 {
           totalSecond -= 1
        } else {
           endTimer()
        }
    }

    func endTimer() {
        timer.invalidate()
    }

    func timeFormatted(_ totalSeconds: Int) -> String {
        let seconds: Int = totalSeconds % 60
        return String(format: "0:%02d", seconds)
    }

}

Variable for your timer

var timer = 60

NSTimer with 1.0 as interval

var clock = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "countdown", userInfo: nil, repeats: true)

Here you can decrease the timer

func countdown() {
    timer--
}

Add this to the end of your code... and call startTimer function with a parameter of where you want to count down to... For example (2 hours to the future of the date right now) -> startTimer(for: Date().addingTimeInterval(60*60*2))

Click here to view a screenshot of iPhone Simulator of how it'll look

extension ViewController
{
    func startTimer(for theDate: String)
    {
        let todaysDate = Date()
        let tripDate = Helper.getTripDate(forDate: theDate)
        let diffComponents = Calendar.current.dateComponents([.hour, .minute], from: Date(), to: tripDate)
        if let hours = diffComponents.hour
        {
            hoursLeft = hours
        }
        if let minutes = diffComponents.minute
        {
            minutesLeft = minutes
        }
        if tripDate > todaysDate
        {
            timer = Timer.scheduledTimer(timeInterval: 1.00, target: self, selector: #selector(onTimerFires), userInfo: nil, repeats: true)
        }
        else
        {
            timerLabel.text = "00:00:00"
        }
    }
    
    @objc func onTimerFires()
    {
        secondsLeft -= 1
        
        //timerLabel.text = "\(hoursLeft):\(minutesLeft):\(secondsLeft)"
        timerLabel.text = String(format: "%02d:%02d:%02d", hoursLeft, minutesLeft, secondsLeft)
        if secondsLeft <= 0 {
            if minutesLeft != 0
            {
                secondsLeft = 59
                minutesLeft -= 1
            }
        }
        
        if minutesLeft <= 0 {
            if hoursLeft != 0
            {
                minutesLeft = 59
                hoursLeft -= 1
            }
        }
        
        if(hoursLeft == 0 && minutesLeft == 0 && secondsLeft == 0)
        {
            timer.invalidate()
        }
        
    }
}

Swift 4

Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(self.updateTime), userInfo: nil, repeats: true)

Update function

@objc func updateTime(){
    debugPrint("jalan")
}

In Swift 5.1 this will work:

var counter = 30

override func viewDidLoad() {
    super.viewDidLoad()

    Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateCounter), userInfo: nil, repeats: true)
}



@objc func updateCounter() {
    //example functionality
    if counter > 0 {
        print("\(counter) seconds to the end of the world")
        counter -= 1
    }
}

Swift4

    @IBOutlet weak var actionButton: UIButton!
    @IBOutlet weak var timeLabel: UILabel!
    var timer:Timer?
    var timeLeft = 60

override func viewDidLoad() {
    super.viewDidLoad()
    setupTimer()
}

func setupTimer() {
    timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(onTimerFires), userInfo: nil, repeats: true)
}

@objc func onTimerFires() {
    timeLeft -= 1
    timeLabel.text = "\(timeLeft) seconds left"

    if timeLeft <= 0 {
        actionButton.isEnabled = true
        actionButton.setTitle("enabled", for: .normal)
        timer?.invalidate()
        timer = nil
    }
}

@IBAction func btnClicked(_ sender: UIButton) {
    print("API Fired")
}

import UIKit

class ViewController: UIViewController {

    let eggTimes = ["Soft": 300, "Medium": 420, "Hard": 720]
    
    var secondsRemaining = 60

    @IBAction func hardnessSelected(_ sender: UIButton) {
        let hardness = sender.currentTitle!

        secondsRemaining = eggTimes[hardness]!

        Timer.scheduledTimer(timeInterval: 1.0, target: self, selector:
            #selector(UIMenuController.update), userInfo: nil, repeats: true)
    }
    @objc func countDown() {
         if secondsRemaining > 0 {
             print("\(secondsRemaining) seconds.")
            secondsRemaining -= 1
        
         }
    }
}

Swift 3

private let NUMBER_COUNT_DOWN   = 3

var countDownLabel = UILabel()
var countDown = NUMBER_COUNT_DOWN
var timer:Timer?


private func countDown(time: Double)
{
    countDownLabel.frame = CGRect(x: 0, y: 0, width: 300, height: 300)
    countDownLabel.font = UIFont.systemFont(ofSize: 300)
    countDownLabel.textColor = .black
    countDownLabel.center = CGPoint(x: self.view.frame.width / 2, y: self.view.frame.height / 2)

    countDownLabel.textAlignment = .center
    self.view.addSubview(countDownLabel)
    view.bringSubview(toFront: countDownLabel)

    timer = Timer.scheduledTimer(timeInterval: time, target: self, selector: #selector(updateCountDown), userInfo: nil, repeats: true)
}

func updateCountDown() {
    if(countDown > 0) {
        countDownLabel.text = String(countDown)
        countDown = countDown - 1
    } else {
        removeCountDownLable()
    }
}

private func removeCountDownLable() {
    countDown = NUMBER_COUNT_DOWN
    countDownLabel.text = ""
    countDownLabel.removeFromSuperview()

    timer?.invalidate()
    timer = nil
}

this for the now swift 5.0 and newst

var secondsRemaining = 60


Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateCounter), userInfo: nil, repeats: true)
}
@objc func updateCounter(){
    if secondsRemaining > 0 {
    print("\(secondsRemaining) seconds.")
    secondsRemaining -= 1
            }
        }

Swift 5 with Closure:

class ViewController: UIViewController {
    
var secondsRemaining = 30
    
@IBAction func startTimer(_ sender: UIButton) {
        
    Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { (Timer) in
        if self.secondsRemaining > 0 {
            print ("\(self.secondsRemaining) seconds")
            self.secondsRemaining -= 1
        } else {
            Timer.invalidate()
        }
    }
            
}

For use in Playground for fellow newbies, in Swift 5, Xcode 11:

Import UIKit

var secondsRemaining = 10
    
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { (Timer) in
    if secondsRemaining > 0 {
        print ("\(secondsRemaining) seconds")
        secondsRemaining -= 1
    } else {
        Timer.invalidate()
    }
}

Swift 5 another way. Resistant to interaction with UI

I would like to show a solution that is resistant to user interaction with other UI elements during countdown. In the comments I explained what each line of code means.

 var timeToSet = 0
 var timer: Timer?

 ...

 @IBAction func btnWasPressed(_ sender: UIButton) {

      //Setting the countdown time
      timeLeft = timeToSet
      //Disabling any previous timers.
      timer?.invalidate()
      //Initialization of the Timer with interval every 1 second with the function call.
      timer = Timer(timeInterval: 1.0, target: self, selector: #selector(countDown), userInfo: nil, repeats: true)
      //Adding Timer to the current loop
      RunLoop.current.add(timer!, forMode: .common)

  }

 ...

 @objc func countDown() {

     if timeLeft > 0 {
         print(timeLeft)
         timeLeft -= 1
     } else {
         // Timer stopping
         timer?.invalidate()
     }
 }

Examples related to xcode

Undefined Symbols error when integrating Apptentive iOS SDK via Cocoapods Xcode 12, building for iOS Simulator, but linking in object file built for iOS, for architecture arm64 iPhone is not available. Please reconnect the device Make a VStack fill the width of the screen in SwiftUI error Failed to build iOS project. We ran "xcodebuild" command but it exited with error code 65 The iOS Simulator deployment targets is set to 7.0, but the range of supported deployment target version for this platform is 8.0 to 12.1 Xcode 10.2.1 Command PhaseScriptExecution failed with a nonzero exit code Git is not working after macOS Update (xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools) Xcode 10: A valid provisioning profile for this executable was not found Xcode 10, Command CodeSign failed with a nonzero exit code

Examples related to swift

Make a VStack fill the width of the screen in SwiftUI Xcode 10.2.1 Command PhaseScriptExecution failed with a nonzero exit code Command CompileSwift failed with a nonzero exit code in Xcode 10 Convert Json string to Json object in Swift 4 iOS Swift - Get the Current Local Time and Date Timestamp Xcode 9 Swift Language Version (SWIFT_VERSION) How do I use Safe Area Layout programmatically? How can I use String substring in Swift 4? 'substring(to:)' is deprecated: Please use String slicing subscript with a 'partial range from' operator Safe Area of Xcode 9 The use of Swift 3 @objc inference in Swift 4 mode is deprecated?

Examples related to nstimer

How can I make a countdown with NSTimer? @selector() in Swift? How can I use Timer (formerly NSTimer) in Swift? How to run a method every X seconds How do I use NSTimer?