Run timer in background
It's possible through a token that identifies a request to run in the background.
Like this: var bgTask = UIBackgroundTaskIdentifier()
Here is how to use it:
var bgTask = UIBackgroundTaskIdentifier()
bgTask = UIApplication.shared.beginBackgroundTask(expirationHandler: {
UIApplication.shared.endBackgroundTask(bgTask)
})
let timer = Timer.scheduledTimer(timeInterval: 10, target: self, selector: #selector(notificationReceived), userInfo: nil, repeats: true)
RunLoop.current.add(timer, forMode: RunLoopMode.defaultRunLoopMode)
I hope it would be useful!
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 3 - How to keep my timer counting even in background?
Okay, so without going to in-depth into your code it appears that you're using a Timer.scheduledTimer
to manually decrement the time set by the user every second.
This is not a good technique as you've found out - it only works when you know you have absolute control over the timing of your application.
Instead, what you should do is store the time when the user starts the alarm, the projected end time, and run a timer to just periodically update the UI.
(My code here isn't perfect, but it should point you in the right direction for solving the problem of keeping a timer running in the background.)
ex.
class ViewController: UIViewController {
// this is pseudo-code as I don't have my compiler open :(
let start: Date!
let end: Date!
func selectionCuisson(selection: Int) {
...
start = Date()
end = Date(timeInterval: tempsCuisson, since: start)
}
}
Then you create a timer that will just update the UI.
// You can set this to be faster than the increment, for a smoother UI experience
// put in compteur()? I think
timer = Timer.scheduledTimer(timeInterval: 0.2, target: self, selector: #selector(ViewController.incrementer), userInfo: nil, repeats: true)
timer.fire()
...
func incrementer() {
let tempsCuisson = end - start
if tempsCuisson < 0 {
// End your Timing Function here
timer.invalidate()
...
lecteur.play()
} else {
minuteurLabel.text = minuteurString(temps: tempsCuisson)
}
}
You can also set a Local Notification to go off when the app goes into the background using the end
date
// when the app becomes inactive
let notification = UILocalNotification()
...
notification.fireDate = end
UIApplication.shared.scheduleLocalNotification(notification)
Related Topics
Fetching Selected Attribute in Entities
Spritekit: Why Does It Wait One Round for the Score to Update? (Swift)
Why Force Unwrapping Is Required in Case of Enum and Switch
Set Text Color and Font for Uidatepicker in iOS8/Swift
Different Cornerradius for Each Corner Swift 3 - iOS
Swift Invalidate Timer Doesn't Work
Done Button Click Event in Avplayerviewcontroller
-[Not a Type Retain]: Message Sent to Deallocated Instance
How to Get a Swift Type Name as a String with Its Namespace (Or Framework Name)
Block_Release Deallocating UI Objects on a Background Thread
Adding Quartzcore to Xcode 4 for iOS
Not Receiving Push Notifications from Firebase
Customize Apps Gallery in Appstore Page
How to Get File Name in Uiimagepickercontroller with Asset Library
iOS Timed Background Processing