How to check for background fetch eligibility?

A user is having problems with my app and I've traced his log files to discover that the user never receives a background fetch opportunity. Every setting seems to be OK, including not being in lo power mode, but nothing ever happens. Users phone is iOS12. The app works fine on my iOS 13 phone and in Simulator for iOS 12.


Is there a way to determine if your app is truly registered for background fetches?


On a related note, it'd be nice to know the availability of all of these, as dictated by the user's choices in Settings:

• iCloud key,value store, NSUbiquitousKeyValueStore.default

• Notifications

• Background app refresh

• Location services



I can check the Notifications:


        let center = UNUserNotificationCenter.current()
        center.getNotificationSettings { settings in
            guard (settings.authorizationStatus == .authorized) else {
                self.logSB.error("Authorization status is NOT authorized")
                return
            }
            self.logSB.debug("Authorization status IS authorized")

            if settings.alertSetting == .enabled {
                // Schedule an alert-only notification.
                self.logSB.debug("Authorization alert is enabled")
            } else {
                // Schedule a notification with a badge and sound.
                self.logSB.error("Authorization alert is NOT enabled")
            }
        }

Found another one! :


        switch UIApplication.shared.backgroundRefreshStatus {
        case .available:
            self.logSB.debug("backgroundRefreshStatus is AVAILABLE")
        case .denied:
            self.logSB.debug("backgroundRefreshStatus is DENIED")
        case .restricted:
            self.logSB.debug("backgroundRefreshStatus is RESTRICTED")
        default:
            self.logSB.debug("backgroundRefreshStatus is unknown")
        }

I'm still trying to diagnose why there is little or no allocation of background time for background fetches for a few troubled users. I uncovered a big clue today by taking a user thru a nuclear re-install: Trash the app, sign out of AppleID, reinstall, open the app, log back into AppleID. This lost all settings but restored normal function of background fetches.


My app uses iCloud storage of key-value data to backup the users settings. This preserves settings thru a normal re-install and also allows the app to be portable to the user's iPad or AppleTV.


Something toxic can also stored there, apparently. Are there any tools for resetting the iCloud data, or for examining it to determine where the toxic information lives? I'm not sure how to proceed.


As an aside, one user does not put his phone on a charger overnight and experienced erratic behavior. I looked into checking the power situation:


let dateFormatter = DateFormatter()
.dateStyle = DateFormatter.Style.medium
.timeStyle = DateFormatter.Style.long
let convertedDate = dateFormatter.string(from: Date())

UIDevice.current.isBatteryMonitoringEnabled = true
var batteryState: UIDevice.BatteryState { UIDevice.current.batteryState }
switch batteryState {
case .unknown:
    self?.logSB.debug("The batteryState is UNKNOWN at \(convertedDate)")
case .unplugged:
    self?.logSB.debug("The batteryState is UNPLUGGED at \(convertedDate)")
case .charging:
    self?.logSB.debug("The batteryState is CHARGING at \(convertedDate)")
case .full:
    self?.logSB.debug("The batteryState is FULL at \(convertedDate)")
default:
    self?.logSB.debug("The batteryState is unknown at \(convertedDate)")
}

var batteryLevel: Float { UIDevice.current.batteryLevel }
self?.logSB.debug("The battery level is \(batteryLevel) at \(convertedDate)")

let myState = UIApplication.shared.applicationState
switch myState {
case .background :
    self?.logSB.info("The app state was found to be Background at \(convertedDate)")
case .inactive:
    self?.logSB.info("The app state was found to be Inactive at \(convertedDate)")
case .active:
    self?.logSB.info("The app state was found to be Active at \(convertedDate)")
default:
    self?.logSB.info("The app state was found to be Unknown at \(convertedDate)")
}
How to check for background fetch eligibility?
 
 
Q