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 ?
- Is there a public API to check if Developer Mode is enabled ?
- Is there a way to tell the location comes from the GPX file ?
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.
CodePudding user response:
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)
}
}