I'm trying to update a countdown timer on my UI that counts down in minutes, so I need to update it every start of a new minute, which is not the same as updating every minute. My current solution is initializing a timer that calls the updateUI() function every tenth of a second, which is far from ideal:
timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector:#selector(TimesViewController.updateUI), userInfo: nil, repeats: true)
Is there a way to call that function every start of a new minute?
Create timer that checks system date in each second. For example;
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { (_) in
let second = Calendar.current.component(.second, from: Date())
if second == 0 {
// new minute
updateUI()
}
}
Related
I try to make a refresh for a label every second in swift 3.
I alway get the following error:
Showing Recent Issues
Command failed due to signal: Segmentation fault: 11
This is the Code I've used:
var TimerBeacon = Timer.scheduledTimer(timeInterval: 1, target: self,
selector: Selector(("Timer")), userInfo: nil, repeats: true)
func Timer() {
//here is the label to refresh
}
I hope someone could help me :)
It looks like your code isn't updated for Swift 3, and could use some better naming conventions.
Create the timer:
let timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(update), userInfo: nil, repeats: true)
This is the function that the timer will call every second:
func update() {
// here is the label to refresh
}
When you want to stop the timer, call invalidate():
timer.invalidate()
You can achieve the same without timer. Use the following code
var iteration = 0
func updateLabel() {
iteration = iteration == Int.max ? 0 : (iteration + 1)
DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
self.label.text = "\(self.iteration)"
self.updateLabel()
})
}
}
Note that I have taken iteration just for example. You can update the label the way you want.
My app is supposed to perform an action whenever the time changes (every minute, not every second). The way that I am achieving this is by creating a Timer object, like so:
var timer = Timer.scheduledTimer(timeInterval: 60, target: self, selector: #selector(ViewController.update), userInfo: nil, repeats: true)
Although this way works it doesn't look very professional because the app doesn't perform the update exactly when the time changes and instead depends on the precise moment the object was created. For example, if the Timer object was created at 10:10:30, then the update will only be performed 30 seconds after the minute changes.
Is there a way that I can know that the minute of the time on the phone changes?
Thanks in advance!
You can schedule the first timer's fire at a specific time, and that time could be the next round minute. Here is an example (copy-and-paste to a playgroung):
import PlaygroundSupport
import Foundation
let cal = NSCalendar.current
var comps = cal.dateComponents([.era, .year, .month, .day, .hour, .minute], from: Date())
comps.minute = comps.minute! + 1
let nextMinute = cal.date(from: comps)
let timer = Timer(fire: nextMinute!, interval: 60, repeats: true) { _ in
print("Minute change")
}
RunLoop.current.add(timer, forMode: .defaultRunLoopMode)
PlaygroundPage.current.needsIndefiniteExecution = true
Note that the timer will not fire if the app is in the background.
Probably a simple question, however, I can't seem to conceive an elegant approach.
I want to design a trivial application that allows a timer to be set to a duration (say 1 minute), after that duration the timer should expire, in the duration the timer should update the UI every second.
Thus if the timer is set to one minute, the timer should fire, update the UI every second (by calling a method) and then finally invalidate after 1 minute.
My conundrum is, I can set a scheduledTimerWithInterval, it calls a method on the timer interval. If I make this 1 minute I can call a method after one minute to invalidate the timer, but there doesn't seem to be a mechanism to perform calls during this minute.
Can you give me some guidance?
I would have done something like this:
1: Declare a timer and a counter:
var timer = Timer()
var counter = 0
2: Create a new function called for example startEverySecond that starts the timer with one second interval, this function is called after 60 seconds and will be called for 1 minute and then invalidate:
func startEverySecond() {
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(everySecond), userInfo: nil, repeats: true)
}
func everySecond(){
if counter == 60{
timer.invalidate()
}
counter = counter + 1
print("Second")
}
3: Handle the start and stop of the timer:
// Start with 60 second interval
timer = Timer.scheduledTimer(timeInterval: 60, target: self, selector: #selector(startEverySecond), userInfo: nil, repeats: false)
// Stop
timer.invalidate()
So basically when you start your timer it will start off with 60 seconds and when this is done it will call the function startEverySecondand this will change the timer to call the everySecondfunction every second for 1 minute. To stop the timer just call timer.invalidate()
Swift 3.x code
Make two global variables
var seconds = 1
var secondTimer:Timer?
Then make these two functions
// for setup of timer and variable
func setTimer() {
seconds = 1
secondTimer?.invalidate()
secondTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateUI), userInfo: nil, repeats: true)
}
//method to update your UI
func updateUI() {
//update your UI here
//also update your seconds variable value by 1
seconds += 1
if seconds == 60 {
secondTimer?.invalidate()
secondTimer = nil
}
print(seconds)
}
finally call setTimer() wherever you want
How can I iterate a for loop overtime in swift? A typical loop will execute immediately as fast as possible. However, I would like to expand the time in which the loop occurs.
Say I have the following loop:
for var i = 0; i < 4; i+=1{
print(i)
}
And I wanted this loop to occur over a span of 1 second, each iteration taking 0.25 seconds. How could I do this? Thanks for any help
You might want to create a Timer like this:
timer = NSTimer.scheduledTimerWithTimeInterval(0.25, target: self, selector: #selector(MyClass.tic), userInfo: nil, repeats: true)
time.fire() //first time
this timer will call the function selected with #selector when it fires, and will fire every 0.25 secondes (first parameter) until you invalidate it. So when you have ended your loops you can
call timer.invalidate()
tic() is a function you can define, and can have any name you want:
func tic() {
numberOfTimeFired = numberOfTimeFired + 1
print(numberOfTimeFired)
}
In Swift 3 the timer declaration would be:
timer = Timer.scheduledTimer(timeInterval: 0.25, target: self, selector: #selector(MyClass.tic), userInfo: nil, repeats: true)
I'm a beginner in Swift and I'm facing a problem.
I want to create a class that contains a timer and a button
Everytime the button is tapped I have to restart the timer, if the time elapsed between the timer starts and the button is tapped is greater (or equal) to 400 milliseconds, I have to call the function in the selector.
But there isn't a "GetTimeElapsed()" method in swift and I don't know how to do it.
If you have some clue/tutorials it could be cool !
Thx guys
Few small steps:
Define the start time: (should happen at the same time you start the timer)
startTime = (NSDate.timeIntervalSinceReferenceDate())
Measure the time difference
let elapsed = NSDate.timeIntervalSinceReferenceDate() - startTime
By default, NSTimer does not have this feature.
Right way is do your job with dates and comparing it.
By the way, you can do a nice extension like this:
public extension NSTimer {
var elapsedTime: NSTimeInterval? {
if let startDate = self.userInfo as? NSDate {
return NSDate().timeIntervalSinceDate(startDate)
}
return nil
}
}
In this way, when you create your timer, you have to set userInfo:
let timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(foo), userInfo: NSDate(), repeats: true)
In your 'foo' method you can test elapsed time:
func foo() {
print(self.timer.elapsedTime)
}