Giovanie Rodz
Giovanie Rodz

Reputation: 1801

How can I make a countdown with NSTimer?

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

Upvotes: 64

Views: 180201

Answers (21)

Mannam Brahmaiah
Mannam Brahmaiah

Reputation: 2283

//MARK:-  IBOutlets 
@IBOutlet weak var verificationTimeVal: NSTextField!

//MARK:-  Declarations 
var secondsRemaining = 5 * 60 //5 minutes
var myTimer : Timer?

override func viewDidAppear() {
    super.viewDidAppear()
    DispatchQueue.main.async {
        //Call the function to start the timer
        self.controlTimer()
    }
}

func controlTimer() {
    myTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] timer in
        if self?.secondsRemaining ?? 0 > 0 {
            let minutes = Int(self?.secondsRemaining ?? 0) / 60
            let seconds = Int(self?.secondsRemaining ?? 0) % 60
            //VerificationTimeVal is a UI element to display the time
            let timerResults = String(format: "%02d:%02d", minutes, seconds)
            self?.verificationTimeVal.stringValue = "\(timerResults) Minutes"
            self?.secondsRemaining -= 1
        } else {
            timer.invalidate()
            //VerificationTimeVal is a UI element to display the time
            self?.verificationTimeVal.stringValue = "00:00 Minutes"
        }
    }
    
    // Add the timer to the current RunLoop
    RunLoop.current.add(myTimer!, forMode: .common)
}

Upvotes: 0

Angie
Angie

Reputation: 1

import UIKit import AVFoundation

class ViewController: UIViewController {

@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var progressBar: UIProgressView!

let eggTime = ["Soft":3, "Medium":4, "Hard":7]
var timer = Timer()
var totalTime = 0
var secondsPassed = 0
var player: AVAudioPlayer!

@IBAction func hardnessSelected(_ sender: UIButton) {

let hardness = sender.currentTitle!
       totalTime = eggTime[hardness]!
       secondsPassed = 0
       progressBar.progress = 0.0
       titleLabel.text = hardness

timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [unowned self] timer in

  if self.secondsPassed < self.totalTime {
                self.secondsPassed += 1
  let progress = Float(self.secondsPassed) /Float(self.totalTime)
                self.progressBar.progress = progress
                print (progress)
            } else {
                 self.timer.invalidate()
                 self.titleLabel.text = "DONE"

Upvotes: -2

zouritre
zouritre

Reputation: 655

Timer with Combine

var counter = 30
    
let cancellable = Timer.publish(every: 1, on: .main, in: .default).autoconnect().sink(receiveValue: { _ in
    counter = counter > 0 ? counter - 1 : 0
    print("timer: ", counter)
})

Upvotes: 0

Hau
Hau

Reputation: 61

For Egg Countdown Timer.

class ViewController: UIViewController {
    var secondsRemaining = 60
    var eggCountdown = 0
    let eggTimes = ["Soft": 5, "Medium": 7,"Hard": 12]
    
    
    
    @IBAction func hardnessSelected(_ sender: UIButton) {
        let hardness = sender.currentTitle!
        let result = eggTimes[hardness]!
        eggCountdown = result * secondsRemaining
        
        Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { (Timer) in
                if self.eggCountdown > 0 {
                    print ("\(self.eggCountdown) seconds.")
                    self.eggCountdown -= 1
                } else {
                    Timer.invalidate()
                }
            }
        
    }
    
}

Upvotes: 6

michael satumba
michael satumba

Reputation: 39

this is an egg timer.

import UIKit

class ViewController: UIViewController {
    let eggTimes = ["Soft": 0.1, "Medium": 2, "Hard": 3]
    
    var eggTime = 0
    
    var timer = Timer()
    
    @IBOutlet weak var label: UILabel!
    
    @IBAction func b(_ sender: UIButton) {
    
    timer.invalidate()
    
    let hardness = sender.currentTitle!
    eggTime = Int(eggTimes[hardness]! * 60)
    timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(update), userInfo: nil, repeats: true)
        }
    @objc func update() {
        if (eggTime > 0) {
            print("\(eggTime) seconds")
            eggTime -= 1
            }
        if (eggTime == 0){
            label.text = ("done")
        }
    }
}

Upvotes: 2

mattroberts
mattroberts

Reputation: 630

You really shouldn’t. Grand Central Dispatch is much more reliable.

Upvotes: 1

Natallyson
Natallyson

Reputation: 41

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
        
         }
    }
}

Upvotes: 1

Gurjinder Singh
Gurjinder Singh

Reputation: 10299

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)
    }

Upvotes: 37

Michael Shulman
Michael Shulman

Reputation: 663

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()
        }
    }
            
}

Upvotes: 54

nullHip_nullSquare
nullHip_nullSquare

Reputation: 75

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()
    }
}

Upvotes: 7

Purple Wolf
Purple Wolf

Reputation: 397

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()
        }
        
    }
}

Upvotes: 1

TomAshTee
TomAshTee

Reputation: 279

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()
     }
 }

Upvotes: 4

Bigman
Bigman

Reputation: 1473

Question 1:

@IBOutlet var countDownLabel: UILabel!

var count = 10

override func viewDidLoad() {
    super.viewDidLoad()

    var timer = Timer.scheduledTimer(timeInterval: 0.4, target: self, selector: #selector(UIMenuController.update), userInfo: nil, repeats: true)
}

func update() {
    if(count > 0) {
        countDownLabel.text = String(count--)
    }
}

Question 2:

You can do both. SpriteKit is the SDK you use for scene, motion, etc. Simple View Application is the project template. They should not conflict

Upvotes: 72

rashed mohammed
rashed mohammed

Reputation: 21

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
            }
        }

Upvotes: 2

user4956851
user4956851

Reputation:

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
    }
}

Upvotes: 74

Devesh.452
Devesh.452

Reputation: 911

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")
}

Upvotes: 2

wsnjy
wsnjy

Reputation: 174

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)
    }

}

Upvotes: 3

luhuiya
luhuiya

Reputation: 2211

Swift 4

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

Update function

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

Upvotes: 2

Giang
Giang

Reputation: 3645

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
}

Upvotes: 5

NikaE
NikaE

Reputation: 624

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-

Upvotes: 1

Henny Lee
Henny Lee

Reputation: 3052

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--
}

Upvotes: 8

Related Questions