i want to print my values in loop after 5 seconds delay
here is how im trying to do so
let count = 1...10
for calls in count{
let seconds = 5
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(seconds), execute: {
print(calls)
})
}
But it waits 5 seconds only in the first time and the print all the values at once.
Maybe there is another way to call a function many times after a delay of time please recommened
this is how im trying with timer
var seconds = 10
var timer = Timer()
override func viewDidLoad() {
super.viewDidLoad()
let count = 1...10
for number in count{
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.counter), userInfo: nil, repeats: true)
print(number)
}
}
#objc func counter(){
seconds -= 1
if (seconds == 0){
print("User Location")
}
}
}
Two pieces of criticisms. Forst, don't use a loop - it's executed immediately. Second, do use threading, there's no need. Use a Timer instead:
class ViewController: UIViewController {
var timer = Timer()
var iterations = 0
override func viewDidLoad() {
super.viewDidLoad()
timer = Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(printTime), userInfo: nil, repeats: true)
}
#objc func printTime() {
print(Date())
iterations += 1
if iterations == 5 {
timer.invalidate()
}
}
}
It's output:
2020-08-15 18:08:38 +0000
2020-08-15 18:08:43 +0000
2020-08-15 18:08:48 +0000
2020-08-15 18:08:53 +0000
2020-08-15 18:08:58 +0000
After 5 iterations, you invalidate the time to shut it off.
I am getting a problem with Swift timer. Timer are not working properly for old iPhone models like iPhone 6. When I printed out time, timer counts every 2 second as 1 second. But if i change withTimeInterval as 0.05, it works a bit better. But still is not work as real life time. Here is my code. Can anyone help me ?
weak var timer: Timer?
var startTime : TimeInterval!
var elapsingTime: Double = 0.0
func configureTimer(totalSecond: Double) {
startTime = Date().timeIntervalSinceReferenceDate
self.invalidateTimer()
DispatchQueue.main.async {
self.timer = Timer.scheduledTimer(timeInterval: 0.02,target: self,selector: #selector(self.advanceTimer(timer:)),userInfo: nil,repeats: true)
}
}
#objc func advanceTimer(timer: Timer) {
elapsingTime += 0.02
self.questionView.configureProgressBar(totalTime: Double(self.totalSecond), elapsingTime: elapsingTime)
self.isTimeExpired = false
self.elapsingTime = Date().timeIntervalSinceReferenceDate - self.startTime
if Int(elapsingTime) == Int(totalSecond) {
self.timer!.invalidate()
self.isTimeExpired = true
self.userAnswerIndex = -1
self.sendAnswer(index: self.userAnswerIndex, isTimeExpired: self.isTimeExpired)
}
}
Timers are not very precise. There precisions is about 0.05 seconds I think. And if a process require a lot of power, your timer will be even more slowed down. The solution can be to save the time when you start your timer and that each time your timer fire, you do a mathematical operation to know how many time passed :
class YourClass {
var startTime : TimeInterval!
//...
func configureTimer() {
startTime = Date().timeIntervalSinceReferenceDate //You add this line
elapsingTime = 0.0
timer?.invalidate()
DispatchQueue.main.async {
self.timer = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true, block: { [weak self] timer in
guard let self = self else { return }
self.elapsingTime = Date().timeIntervalSinceReferenceDate - self.startTime //You change this one
self.questionView.configureProgressBar(totalTime: self.totalTime, elapsingTime: self.elapsingTime)
self.questionView.videoQuestionPlayer.player?.play()
if Int(self.elapsingTime) == Int(self.totalTime) {
self.timer!.invalidate()
self.isTimeExpired = true
self.sendAnswer(index: -1)
}
})
}
}
}
I would try setting it up like this.
var myTimer = Timer()
var counter = 0.0
myTimer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(yourTargetFunctionHere), userInfo: nil, repeats: true)
#objc func yourTargetFunctionHere() {
//in here is where you do all your code work
counter += 0.1
if counter == yourElapsedTime {
//when your target time is hit do something here
}
if counter == finishedTime {
self.timer.invalidate()
self.counter = 0
}
}
Im trying to make a countdown timer. everything works fine except that my timer does not count at regular intervals (1sec); instead it counts all the way down instantly giving me 0 every time. did a lot of search without luck. All examples I could find show similar timeInterval parameter.
var timer = Timer()
var remainingTime = 120
#objc func timerCount () {
if remainingTime > 0 {
while remainingTime > 0 {
remainingTime -= 1
timerLabel.text = String(remainingTime)
print(remainingTime)
}
} else {
timer.invalidate()
}
}
#IBAction func pauseButton(_ sender: Any) {
timer.invalidate()
}
#IBAction func playButton(_ sender: Any) {
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.timerCount), userInfo: nil, repeats: true)
}
The reason your code is not working is that you have put an unnecessary while loop in your timerCount() method. You don't need to do this. Your timer will fire this method after each time interval. At very first call this while loop make your remainingTime to 0. This is why you are instantly getting 0 every time.
You just need to remove that while loop.
Can You try like this
var timer = Timer()
var remainingTime = 120
#objc func timerCount () {
let date = NSDate()
let nowdate = UserDefaults.standard.object(forKey: "NowDate") as! Date
let miniute = nowdate.timeIntervalSince(date as Date)
print(Int(miniute))
if (Int(miniute) == 0) {
timer.invalidate()
UserDefaults.standard.removeObject(forKey: "NowDate")
} else {
timerLabel.text = String(Int(miniute))
}
}
#IBAction func pauseButton(_ sender: Any) {
timer.invalidate()
UserDefaults.standard.removeObject(forKey: "NowDate")
}
#IBAction func playButton(_ sender: Any) {
let CurrentDate = NSDate()
let NowDate = CurrentDate.addingTimeInterval(TimeInterval(remainingTime))
UserDefaults.standard.set(NowDate, forKey: "NowDate")
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.timerCount), userInfo: nil, repeats: true)
}
I have an app that takes the time and time interval from a user and starts to count down at that time.
when I try to start the timer at the time that I have, it freaks out and not working.
this is the func that runs the timer:
func runTimer(){
let timer = Timer(fireAt: firstMealTime, interval: 1, target: self, selector: #selector(updateTimer), userInfo: nil, repeats: true)
RunLoop.main.add(timer, forMode: .commonModes)
}
and this is the updateTimer func:
if seconds < 1 {
timerRepeat! -= 1
updateMealLeftLabel(numberOfMeal: timerRepeat)
resetTimer()
}else{
seconds -= 1
updateTimerLabel()
}
thanks in advance!
You can check your timer definition like this:
var seconds = YourCountdownValue // (in seconds) for example 100 seconds.
func runTimer(){
firstMealTime = Date().addingTimeInterval(10.0) // This line is for testing. Countdown will be start in 10 seconds.
let timer = Timer(fireAt: firstMealTime, interval: 1, target: self, selector: #selector(updateTimer), userInfo: nil, repeats: true)
RunLoop.main.add(timer, forMode: .commonModes)
}
func updateTimer() {
if seconds < 1 {
timerRepeat! -= 1
updateMealLeftLabel(numberOfMeal: timerRepeat)
print("finished") //for testing
resetTimer()
}else{
seconds -= 1
print(seconds) //for testing
updateTimerLabel()
}
}
I'm developing a game and I want to create a pause menu. Here is my code:
self.view?.paused = true
but NSTimer.scheduledTimerWithTimeInterval still running...
for var i=0; i < rocketCount; i++ {
var a: NSTimeInterval = 1
ii += a
delaysShow = 2.0 + ((stimulus + interStimulus) * ii)
var time3 = NSTimer.scheduledTimerWithTimeInterval(delaysShow!, target: self, selector: Selector("showRocket:"), userInfo: rocketid[i], repeats: false)
}
I want time3 to pause the timer when player click pause menu and continue run the timer when player come back to the game, but how can I pause NSTimer.scheduledTimerWithTimeInterval? help me please.
You need to invalidate it and recreate it. You can then use an isPaused bool to keep track of the state if you have the same button to pause and resume the timer:
var isPaused = true
var timer = NSTimer()
#IBAction func pauseResume(sender: AnyObject) {
if isPaused{
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("somAction"), userInfo: nil, repeats: true)
isPaused = false
} else {
timer.invalidate()
isPaused = true
}
}
To Start:
timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: Selector("updateView"), userInfo: nil, repeats: true)
To Resume:
timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: Selector("updateView"), userInfo: nil, repeats: true)
To Pause:
timer.invalidate
This worked for me. The trick is that do not look for something like "timer.resume" or "timer.validate". Just use "the same code for starting a timer" to resume it after the pause.
To start
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.action), userInfo: nil, repeats: true)
To pause
timer.invalidate()
To reset
time += 1
label.text = String(time)
'label' is the timer on output.
I was just working through a similar problem with my game, and found an easy solution.
First I should point out like others have, that Timer and NSTimer doesn't have a pause function. You have to stop the Timer with Timer.invalidate(). After invalidating a Timer, you must initialize it again to start the Timer. To quote from https://developer.apple.com/documentation/foundation/timer, the function .invalidate() -
Stops the timer from ever firing again and requests its removal from
its run loop.
To pause a timer we can use Timer.fireDate, this is where Timer (and NSTimer) saves the date for when the Timer will fire in the future.
Here's how we can pause a Timer by saving the seconds left that the Timer has until it fires again.
//The variable we will store the remaining timers time in
var timeUntilFire = TimeInterval()
//The timer to pause
var gameTimer = Timer.scheduledTimer(timeInterval: delaysShow!, target: self, selector: #selector(GameClass.showRocket), userInfo: rocketid[i], repeats: false)
func pauseTimer()
{
//Get the difference in seconds between now and the future fire date
timeUntilFire = gameTimer.fireDate.timeIntervalSinceNow
//Stop the timer
gameTimer.invalidate()
}
func resumeTimer()
{
//Start the timer again with the previously invalidated timers time left with timeUntilFire
gameTimer = Timer.scheduledTimer(timeInterval: timeUntilFire, target: self, selector: #selector(GameClass.showRocket), userInfo: rocketid[i], repeats: false)
}
Note: Don't invalidate() the Timer before getting the fireDate. After invalidate() is called the Timer seems to reset the fireDate to 2001-01-01 00:00:00 +0000.
2nd Note: A timer can potentially fire after its set fireDate. This will lead to a negative number, which will default the Timer to run after 0.1 milliseconds instead. https://developer.apple.com/documentation/foundation/timer/1412416-scheduledtimer
To stop it
time3.invalidate()
To start it again
time3.fire()
You can not resume the timer back.
Instead of resuming - just create a new timer.
class SomeClass : NSObject { // class must be NSObject, if there is no "NSObject" you'll get the error at runtime
var timer = NSTimer()
init() {
super.init()
startOrResumeTimer()
}
func timerAction() {
NSLog("timer action")
}
func pauseTimer() {
timer.invalidate
}
func startOrResumeTimer() {
timer = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: Selector("timerAction"), userInfo: nil, repeats: true)
}
}
Even though the solutions exposed here are good, I thought an important insight was missing. Like a lot of people here explained, timer invalidate() and recreate is the best option. But one could argue that you could do something like this:
var paused:Bool
func timerAction() {
if !paused {
// Do stuff here
}
}
is easier to implement, but it will be less efficient.
For energy impact reasons, Apple promotes avoiding timers whenever possible and to prefer event notifications. If you really need to use a timer, you should implement pauses efficiently by invalidating the current timer. Read recommendations about Timer in the Apple Energy Efficiency Guide here:
https://developer.apple.com/library/content/documentation/Performance/Conceptual/EnergyGuide-iOS/MinimizeTimerUse.html
SWIFT3
Global Declaration :
var swiftTimer = Timer()
var count = 30
var timer = Timer()
#IBOutlet weak var CountDownTimer: UILabel!
viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
BtnStart.tag = 0
}
Triggered IBACTION :
#IBAction func BtnStartTapped(_ sender: Any) {
if BtnStart.tag == 0 {
BtnStart.setTitle("STOP", for: .normal)
timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(ScoreBoardVC.update), userInfo: nil, repeats: true)
BtnStart.tag = 1
} else {
BtnStart.setTitle("START", for: .normal)
timer.invalidate()
BtnStart.tag = 0
}
}
Function that Handles The things :
func update(){
if(count > 0){
let minutes = String(count / 60)
let ConvMin = Float(minutes)
let minuttes1 = String(format: "%.0f", ConvMin!)
print(minutes)
let seconds = String(count % 60)
let ConvSec = Float(seconds)
let seconds1 = String(format: "%.0f", ConvSec!)
CountDownTimer.text = (minuttes1 + ":" + seconds1)
count += 1
}
}
Pause timer : timer.invalidate()
and
Resume timer : recreate timer. it's work fine.
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(mainController.updateTimer), userInfo: nil, repeats: true)