Search code examples
iosswiftbackground-task

Why does logging backgroundTimeRemaining show a wrong/big number even though app was moved to background?


I'm logging my UIApplication.shared.backgroundTimeRemaining but the number is huge. It's almost 200 digits.

This is how I'm logging it.

 os_log("Lat: %f | Long:  %f | RemainingTime: %f ", log: log, type: .default, location.coordinate.latitude, location.coordinate.longitude, UIApplication.shared.backgroundTimeRemaining)

I thought there is something wrong with the format of my logging so I also tried placing a breakpoint and printing it but still the number that it logs is the same huge number. I also looked into this question which has a fair explanation, that is if your app is in foreground then the time would be that huge. But I still see this number even if there has been 5 minutes since I've moved the app to background.

A sample number I get for my remainingTime is:

179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000

Entire code:

import UIKit
import CoreLocation
import os.log
import MapKit

class ViewController: UIViewController, CLLocationManagerDelegate{

    lazy var locationManager : CLLocationManager = {
        var manager = CLLocationManager()
        manager.delegate = self

        manager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
        manager.distanceFilter = 1
        manager.pausesLocationUpdatesAutomatically = true
        manager.allowsBackgroundLocationUpdates = true
        manager.requestAlwaysAuthorization()
        manager.startUpdatingLocation()
        return manager
    }()

    var lastLocation : CLLocation?

    var mapView : MKMapView?

    let log = OSLog(subsystem: "XYZ.LocationAppSubSystem", category: "dumbo")

    override func viewDidLoad() {
        super.viewDidLoad()

        if locationManager.location != nil{

        }else {

            DispatchQueue.main.async {
                self.locationManager.startUpdatingLocation()
            }

        }
        os_log("view was Loaded", log: log, type: .error)

        mapView = MKMapView(frame: UIScreen.main.bounds)
        mapView?.showsUserLocation = true
        view.addSubview(mapView!)

    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

        guard let location = locations.last else {
            return
        }
        lastLocation = location
        //        let date = Date().description(with: Locale.current)

        os_log("Lat: %{public}f | Long:  %{private}f | RemainingTime: %{public}f ", log: log, type: .default, location.coordinate.latitude, location.coordinate.longitude, UIApplication.shared.backgroundTimeRemaining)

    }

    func locationManagerDidPauseLocationUpdates(_ manager: CLLocationManager) {
        os_log("locationManager was paused", log: log)

        let location = lastLocation

        os_log("Lat: %{public}f | Long:  %{private}f | RemainingTime: %{public}f ", log: log, type: .default, (location?.coordinate.latitude)!, (location?.coordinate.longitude)!, UIApplication.shared.backgroundTimeRemaining)


    }

    func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
        os_log("Region was exited", log: log)
    }

    func createRegion(location: CLLocation) {

        let radius = 3.0

        let region = CLCircularRegion(center: location.coordinate, radius: radius, identifier: "didPauseLocationUpdates")
        region.notifyOnExit = true
        region.notifyOnEntry = false

        locationManager.startMonitoring(for: region)
    }

    func locationManager(_ manager: CLLocationManager, monitoringDidFailFor region: CLRegion?, withError error: Error) {
        if region?.identifier == "didPauseLocationUpdates"{
            os_log("Main Region was Failed to be created", log: log)
        }else{
            os_log("Other regions were checked ", log: log)
        }
    }


}

Solution

  • I can think of two reasons:

    • If the app is set to always track your location, like Google Maps, then if you ever began tracking then it will indefinitely continue tracking.

    • If the app was connected to Xcode, then since Xcode wants to continuously debug the app, Xcode is greedy, it won't ever all the app to get backgrounded.

    debugging code that runs in the background on iOS is tricky because the act of running your app in the debugger affects how it behaves.
    ...

    Xcode’s debugger prevents the system from suspending your app. If you run your app from Xcode, or you attach to the process after launch, and then move your app into the background, your app will continue executing in situations where the system would otherwise have suspended it.

    Simulator may not accurately simulate app suspend and resume.

    If the app is untethered from Xcode, then the background remaining time will be normal.