I have a framework that returns a ViewController to my app upon request.
This view controller contains a QR code that is subjected to change after a certain period of time - say 3 days.
I would like to call a method contained inside the framework after 3 days so that the changed/updated QR is readily available even if the user is not using the app actively. When user opens the app - the updated QR is there!
For that, I have used below in my ViewController inside the framework - (from tutorial link)
//MARK:- Add Timer to run QR Logic after 5 seconds
let date = Date().addingTimeInterval(5)
let timer = Timer(fireAt: date, interval: 0, target: self, selector: #selector(QrUIViewController.performQrFetchLogic), userInfo: nil, repeats: true)
RunLoop.main.add(timer, forMode: RunLoopMode.commonModes)
This piece of code works perfectly when app is active/background. Is it possible, and how to achieve this even if the app is killed?
PS: I read Jobscheduler and AlarmManager will work for Android - is there something similar to these in iOS?
The best way to achieve this is probably using a scheduled Local Notification.
You schedule local notification for some time in the future and then afterwards react to it. This is the case both for when the app is active, in background or inactive.
Remember that notifications do not fire if the user kills your app.
Related
This question already has answers here:
How to call a function when the app is inactive (e.g. playing music in background)?
Swift 3 - How to make timer work in background
(10 answers)
Closed 2 years ago.
I am trying to execute a simple function that runs a Timer in the background of the app.
In short,
A 10 second Timer starts as soon as app begins
I lock the device after seeing confirmation the Timer has begun in the Foreground
10 seconds later, with the app in the Background, I should expect a log to appear. This currently works in the simulator but not on the device
Full code below. You can also download the app itself to try.
After consulting popular answers such as this (which also contains conflicting answers about whether a Timer actually runs in the background or not), I am not exactly what the authoritative answer is on at the topic.
Any help is appreciated.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var timer : Timer?
if timer == nil {
NSLog("Timer started")
timer = Timer.scheduledTimer(withTimeInterval: 10, repeats: true, block: {_ in NSLog("After 10 seconds show up") //this will not work on a device
//Also, I get the error: Can't end BackgroundTask: no background task exists with identifier 1 (0x1), or it may have already been ended. Break in UIApplicationEndBackgroundTaskError() to debug.
})
}
}
}
It may be confusing, but questions like that actually do answer the question. Bottom line, the app is completely suspended (including timers) when the app enters the background. You can, however, request a little time before it is suspended as outlined in Extending Your App’s Background Execution Time. You’ll see many online references to this being able to allow an extra three minutes of background execution before it is suspended, but in iOS 13 this has been further reduced down to only 30 seconds.
Now, apps that have legitimate need or background execution (e.g. a navigation app, a VOIP app, a music playing app, etc.) can request special background execution modes (see About the Background Execution Sequence, but none of these are intended solely for the purpose of keeping a timer running in the background.
If you want to notify a user at some designated time in the future, use user notification service. But do not just attempt to keep your app running in the background.
By the way, while that link describes the process, their code snippet is misleading. See https://stackoverflow.com/a/23831862/1271826 for a more contemporary rendition.
Hello I am developing the Application in which i need to send Data in Http request every 10 seconds. it's working fine when app is in running state but it will stop as soon as it will goes in background or inactive state.
Your app need to support a couple of things.
If your app can have the background-running capability then you can do a couple of things.
To run periodically you will need a Timer (NSTimer).
You will need a method which will execute the HTTP request.
Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(callWebservice), userInfo: nil, repeats: true)
func callWebservice() {
// Handle response
}
Also please refer : https://developer.apple.com/library/archive/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html
I am making an app that helps people with tracking down the working intervals.
What I need is the timer should run at least 30 minutes regardless of the app is in foreground or background.
func startFocus() {
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(Pomodoro.focusIntervalCounter), userInfo: nil, repeats: true)
}
func focusIntervalCounter() {
dynamic_focusIntervalSecond -= 1
focusDelegate?.updatingFocusCountingDown(timeStamp: seconds2Timestamp(intSeconds: dynamic_focusIntervalSecond), secondLeft: dynamic_focusIntervalSecond)
if dynamic_focusIntervalSecond == 0 {
timer.invalidate()
focusDelegate?.focusCountingDowndid(end: true)
}
}
focusIntervalCounter() should invalid the timer when the `dynamic_focusIntervalSecond` is 0.
It works fine when the program is in the foreground, but after the screen is shut, the timer just works a little while and stop.
Is this any approach to continue the timer's counting?
Thanks in advance.
No, you can run background tasks for up to 5 minutes, use the background update functionality to trigger app refresh, or use notifications to trigger background actions. There is no way in iOS to guarantee that any code will be run consistently in the background after 30 minutes. Local notifications will enable your code to run after the user selects an action in a notification. Silent push notifications can run some code in the background open receipt, but require an internet connection and are not guaranteed to be delivered.
See this question for more info:
iOS Timer in the background
No, You cannot run Timers in background mode. You can create a UIBackgroundTaskIdentifier which will give you 180sec as i have observed, i'm not sure it might vary with OS version.
You can try scheduling local notifications for 30 mins.
You can enable back ground modes if you're using push notification, Airplay, Location, VOIP apps, Bluetooth, News stand, Background fetch, for more details read this apple developer document BackgroundExecution
Some things are not possible in background, Have you switched your project to enable the background modes? You can reed more about it here
I'm trying to run an NSTimer task:
timerUploadData = NSTimer.scheduledTimerWithTimeInterval(60 * 1, target: self, selector: "uploadData", userInfo: nil, repeats: true)
But it only work when we have the app in background, but I wan't to still run this even if the app is stopped by doing double tap on home and slide the app to the top to kill it. How to do this ?
If the user kills the app, it is no longer running, therefore your code is no longer running. There is no such state that your code/app can be in where this is possible.
I think you should read the app life cycle document.
Is there any method to call a web service automatically?
Currently i am developing an app like Taxi related app by using Google Maps SDK.
I had 2 applications like DRIVER & RIDER. If Driver login in to the application. When ever In User application user should press the request ride then only i want to display Count down timer in Driver app by using web services
The main thing is --> In DRIVER application there was an screen like "Main Screen"(following image). There is no refresh button. How can i get User request in Same screen automatically refresh the UIViewController screen when ever driver get request from server end.
I know some default methods like: ViewDidLoad, ViewWillAppear, ViewWillDisAppear and etc.., --> these all methods call while specific time only like coming from one screen to another (or) while dismiss
In my case how can i rectify this issue
Already i used code like:
NSTimer* myTimer = [NSTimer scheduledTimerWithTimeInterval: 60.0 target: self
selector: #selector(callAfterSixtySecond:) userInfo: nil repeats: YES];
After each 60.0 second , iOS will call the below function
-(void) callAfterSixtySecond:(NSTimer*) t
{
//Here i call my server API
}
But this is not the feasable solution
You can send Push notification to from your server, this will could be use to trigger events in your application. You can do it without notification.
Check this for example:
http://hayageek.com/ios-silent-push-notifications/'
That's would be an easy way, now if you want to get complex read up on the Inter-process communication