Active app being sent to background - why?

I've been struggling to figure out why my app misbehaves for a few users. Their systems seem to be hostile towards the app. It's being sent to the background from the active state, and once in the background it seems to be quickly suspended. I do not see this on my phone or in Simulator, so it's very hard to diagnose. I have good logging that can detail background operation, but the logs die along with the app.


The app is designed for longrun operation in the background. When the system allows, it gets some web data and reports to the user via a local notification. It's complicated but it all works, except for a few users.


The app additionally has a "Night Mode", where it remains the active app all night and web data is gathered every 10 minutes on a timer. Mine ran perfectly all night last night but a user log shows the app was backgrounded after just 3 minutes. It must have also suspended shortly after that because there are zero log entries until the user woke up in the morning and logging resumed. That particular user is getting some background fetches this morning, so at least we know the proper permission settings are in place.


What would cause an app to be so aggressively demoted?

Replies

I was just reminded that I've fought this battle before:

https://forums.developer.apple.com/thread/82830


Maybe I'll trying upping the timer tolerance again.

My disappearing app problem still happens with the timer tolerance set to 180, my timer code below.


When my app enters "NightMode", I disable the Idle timer to keep the app active and in the foreground all night, and I turn on the proximity monitor to allow the screen to go black when the phone is placed face down.


        UIApplication.shared.isIdleTimerDisabled = true
        UIDevice.current.isProximityMonitoringEnabled = true


A user's log shows that the .isIdleTimerDisabled = true was correct at 1:36AM and again at 1:46AM. The log then goes blank, meaning the app was "dead". My app is heavily logged for debugging and won't do hardly anything without making a log entry. After 1:46 there was nothing about any of these events, which should all generate log entries:


applicationWillResignActive
applicationDidEnterBackground
applicationWillTerminate


The app came back to life and logging in the background at 4:11AM this morning. It reported that the .isIdleTimerDisabled = false at that time. How did it get reset? What the heck happened to my app after 1:46AM?



Starting my timer for NightMode:


    weak var timer: Timer?
    func startTimer() {
        timer?.invalidate()   // just in case you had existing `Timer`, `invalidate` it before we lose our reference to it
        if #available(iOS 10.0, *) {
            timer = Timer.scheduledTimer(withTimeInterval: 600.0, repeats: true) { [weak self] _ in
                self?.timer?.tolerance = 180  // Upped from 80 on 5/27/20
                let dateFormatter = DateFormatter()  // format the date for output
                dateFormatter.dateStyle = DateFormatter.Style.medium
                dateFormatter.timeStyle = DateFormatter.Style.long
                let convertedDate = dateFormatter.string(from: Date())
                self?.logSB.warning("The timer triggered at \(convertedDate)")
            }
        } else {
            // Fallback on earlier versions
        }
    }
How can I diagnose this? Unexpected demotion to the background continues to plague me. It happens only rarely and may only affect some users.

My app is the active one, but suddenly is sent to the background. I've tried to use logging to sort it out but I see no evidence of low power, no memory warning, nothing except the .applicationWillResignActive event.

In the most recent event, background operation commenced and app refreshes continued normally. But I need the app to stay active when that's what the user expects!