Different app behavior when running on device from Xcode

I have an app I am working on that makes a REST call, updates the UI with the info, and sends a notification. When I run Build and Run my app from Xcode using my iPhone as the destination, it works exactly as I want it to - my REST calls and notifications continue to work when the app is in the background.

However, when I run my app that has been installed on my iPhone from the Xcode build/run directly (without Xcode in the picture), it does NOT behave correctly and only works when my app is in the foreground.

What am I missing?

Clarification - when not running through Xcode, my app stops making my REST calls/notifications, which are on run repeatedly using a Timer

Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in

How do you go from REST to Timer? Why are you using Timer? I would avoid using Timer unless I literally need to run an internal clock. What exactly is your definition of REST? Use of URLSession? And which framework?

In case you didn't know, Timer doesn't run in background.

Thank you for your post @briggr1 . The information provided by @Tomato is highly valuable, is your intention is to create a testing application that sends requests every x minutes. In that case, please clarify your specific requirements. If the application is intended to run in the background, you may consider disabling that feature within the app’s settings. Is this application intended for macOS or iOS?

Are you using iOS as standard iOS lifecycle. Is the app going to the background if the user swipes to the home screen, iOS gives your app a few seconds to finish what it's doing, and then completely suspends it to save battery. Any Timer, DispatchQueue, or standard network calls you have running will freeze immediately.

You can ask iOS for up to ~30 seconds of extra time to finish the task. Use UIApplication.shared.beginBackgroundTask(expirationHandler:). Once the task finishes, you must call endBackgroundTask, or iOS will forcefully kill your app.

In macOS, to prevent this, you use the ProcessInfo API to tell macOS that your app is doing important work.

And as Tomato said, use URLSession Even if your app is completely suspended or terminated, iOS finishes the network request and then wakes your app up in the background to hand you the data.

Please go in detail about what you are trying to accomplish on your app and we can give you better advice of how to accomplish it.

Albert
  Worldwide Developer Relations.

Thank you @Tomato and @DTS Engineer !

The purpose of my app is to provide a notification mechanism when there are drastic air quality changes.

To accomplish this, I have an async function that makes a GET request to an air quality sensor (using UrlSession), decode the payload, and then do comparisons with previous readings. If the readings have changed drastically, an UNMutableNotificationContent() is scheduled.

Currently, my async function is called from within a repeating scheduled timer so that I can poll my sensor every minute:

                        Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
     timerVal -= 1
     if timerVal == 0 {
          timerVal = startVal
          getAQI()
     }
}

This all works just fine (including when the app is in the background) ONLY when I run the app from Build and Run in Xcode on my dev iPhone as the destination. I've left the app running this way for hours in the background and with the phone locked and it works great!

However, when I try to run the app purely from the app shortcut on my iPhone, it works fine when in the foreground but it no longer runs the Timer wrapped functions in the background.

@DTS Engineer - given your statement

Any Timer, DispatchQueue, or standard network calls you have running will freeze immediately.

Maybe it's a bug that Xcode allows myTimer to keep running in the background?

I am completely open to learning any way to accomplish the functionality I need. I've been reading about BGAppRefreshTask, but it sounds like it does not give me the time guarantee that I need to fetch critical data every x minutes and be notified in a possible approaching fire scenario.

Different app behavior when running on device from Xcode
 
 
Q