How to properly measure elapsed time in background in Swift
Ok, like I mention in the edit 2 of the question:
The first issue was because "seconds" is a Int and then it almost always gains or lose when converting it from Double.
But the main problem was that i had to invalidate the timer when the app enter in background and i didn't.
So now with invalidating the timer when the app gets the notification that will enter background and then starting it when it enter foreground everything works fine.
swift calculate time for timers running in background
Personally, I'd consider the combined duration of A and B to be one "cycle". And then, when the app restarts, I'll do the modulus calculations to determine (a) how many cycles have past since timer A was started the first time; and (b) calculate where we are within the current cycle. From that you can easily calculate the amount of time left until the next occurrence of each timer:
let elapsed = Date().timeIntervalSince(startTime)
let totalDuration = durationOfTimerA + durationOfTimerB
let whereInCycle = elapsed.remainder(dividingBy: totalDuration)
let cycleCount = Int(elapsed / totalDuration)
var timeUntilNextA: Double
var timeUntilNextB: Double
if whereInCycle < durationOfTimerA {
timeUntilNextA = durationOfTimerA - whereInCycle
timeUntilNextB = timeUntilNextA + durationOfTimerB
} else {
timeUntilNextB = durationOfTimerA + durationOfTimerB - whereInCycle
timeUntilNextA = timeUntilNextB + durationOfTimerA
}
if cycleCount < 1 {
if whereInCycle < durationOfTimerA {
print("timer A hasn't fired yet")
} else {
print("timer A has fired, but B hasn't")
}
} else {
if whereInCycle < durationOfTimerA {
print("both timers A and B have fired \(cycleCount) times, and waiting for A to fire next")
} else {
print("timers A has fired \(cycleCount+1) times, but B has fired only \(cycleCount) times; we waiting for B to fire next")
}
}
print("A will fire in \(timeUntilNextA) seconds; B will fire in \(timeUntilNextB)")
Background timer running
Until iOS 12, you could not been able to run your app in background mode, but from iOS 13 (beta) you can.
Apple has added framework BackgroundTasks
which can add ability to do some task in background mode.
https://developer.apple.com/documentation/backgroundtasks/bgtaskscheduler
Swift timer in background
It's not possible to run timer continuously in the background after a couple seconds apple may discard the timer.
You can do one thing, take one global variable add set current time in applicationDidEnterBackground
, and applicationWillEnterForeground
check in this method take current system time and stored previous time compare both times and get a difference between them and check is,
if self.currentTime != TIME_SEARCH {
self.currentTime += 1
}
else {
// Time out
self.stopChecking()
}
You have to check here like if self.currentTime > TIME_SEARCH
or if self.currentTime < TIME_SEARCH
so you can get perfect result. :)
Related Topics
Use Quick Look Inside a Swift Cocoa Application to Preview Audio Files
Swift - Encode and Decode a Dictionary [String:Any] into Plist
Swift 4: Validating Credit Card Expiration Date
How to Make Uicollectionview Reload Once It Receives Data from Firebase
Firebase Access Keys in Queryorderby
Find Out When Uikeyboard.Frame Intersects with Other Frame
Swift MAC App, Run Terminal Command Without Knowing the Path (So It Looks in Every Path in $Path)
Swift 'Unable to Dequeue a Cell with Identifier Intervalcellidentifier
Text from [String] to a Label.Text Isn't Working the First Time
Programmatically Scroll Nsscrollview to the Right
Swift Skshapenode Shapewithsplinepoints
How to Resolve Error in Unit Testing When We Have Date Comparison in Codable
How Marquee Text of Label on Swift
Swift: Get 30 Days Before 'Specific Date'
Alternative to Switch Statement in Swiftui Viewbuilder Block