Reputation: 1801
How can I make a countdown with an NSTimer
using Swift?
Upvotes: 64
Views: 180201
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
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
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
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
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
Reputation: 630
You really shouldn’t. Grand Central Dispatch is much more reliable.
Upvotes: 1
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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