iosswiftxcodegpxios16

iOS - Check if Developer Mode is ON (Swift)


My App relies on checking user location upon start. On iOS 16, when the user enables the Developer Mode on Privacy Settings they can simulate any location on the device using a GPX file.

The device actually changes the location of the device and most apps that I use actually think my location is the one on the GPX file. Is there a way to make sure the location is the actual user location or a simulated one ?

Even if the Developer mode is turned off it takes restarting the device to pick up the actual location again , so not sure if there is a different and better solution to this.

Thank you.


Solution

  • Apple provides sourceInformation on each CLLocation object returned. Checking the isSimulatedBySoftware parameter will give a boolean response.

    Core Location sets isSimulatedBySoftware to true if the system generated the location using on-device software simulation. You can simulate locations by loading GPX files using the Xcode debugger. The default value is false.

    The code below is a full functioning example that will turn the screen red if a simulated location is detected. I have confirmed that toggling simulated locations on/off in Xcode will make the screen turn from green to red and back again.

    import UIKit
    import CoreLocation
    
    class ViewController: UIViewController {
        
        let locationManager = CLLocationManager()
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            // setup location monitoring
            locationManager.delegate = self
            locationManager.requestWhenInUseAuthorization()
        }
    }
    
    extension ViewController: CLLocationManagerDelegate {
        func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
            // list of locations that are simulated
            let simulatedLocations = locations.filter { $0.sourceInformation?.isSimulatedBySoftware == true }
            view.backgroundColor = simulatedLocations.count > 0 ? .red : .green
        }
        
        func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
            guard manager.authorizationStatus == .authorizedAlways || manager.authorizationStatus == .authorizedWhenInUse else { return }
            locationManager.startUpdatingLocation()
        }
        
        func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
            print(error.localizedDescription)
        }
    }