How does Core Location work: authorization levels, accuracy, significant-change and visits, and geofencing?
Predict first
What is the distance between Pune and Mumbai, and does a 200 m geofence around Pune contain a point a few metres away and Mumbai?
import CoreLocation
let pune = CLLocation(latitude: 18.5204, longitude: 73.8567)
let mumbai = CLLocation(latitude: 19.0760, longitude: 72.8777)
print(Int(pune.distance(from: mumbai) / 1000))
let region = CLCircularRegion(center: pune.coordinate, radius: 200, identifier: "pune")
print(region.contains(CLLocationCoordinate2D(latitude: 18.5205, longitude: 73.8568)), region.contains(mumbai.coordinate))
print(CLLocationCoordinate2DIsValid(CLLocationCoordinate2D(latitude: 91, longitude: 0)))
- 120, then true false, then false
- 1200, then true true, then true
- 120, then false false, then true
Predict first
What are the authorization status values and the accuracy constants?
import CoreLocation
print(CLAuthorizationStatus.notDetermined.rawValue, CLAuthorizationStatus.authorizedAlways.rawValue, CLAuthorizationStatus.authorizedWhenInUse.rawValue)
print(kCLLocationAccuracyBest, kCLLocationAccuracyKilometer, kCLDistanceFilterNone)
- 0 3 4, then -1.0 1000.0 -1.0
- 0 1 2, then 0.0 1.0 0.0
- 3 4 0, then 100.0 10.0 5.0
Mental model. Continuous high-accuracy GPS is leaving a taxi meter running while you shop. Significant change and geofences are asking the taxi company to ring you when you have moved a long way or reached a particular door.
A CLLocationManager delivers locations to its delegate. Authorization has levels: When In Use (only while the app is visible or running a foreground-started session; the status is 4 on iOS) and Always (3; also in the background and relaunch), with the user able to choose Precise or Approximate location (accuracyAuthorization) and Allow Once. Request requestWhenInUseAuthorization() first and escalate to requestAlwaysAuthorization() only when a feature truly needs background tracking; the Info.plist usage strings (NSLocationWhenInUseUsageDescription, …AlwaysAndWhenInUse…) are required and are shown to the user. The modern API surface is CLLocationUpdate.liveUpdates() (async sequence) and CLServiceSession on iOS 17+, with the delegate API still common. Accuracy and distance filter are the battery knobs: desiredAccuracy ranges from kCLLocationAccuracyBest (GPS plus sensors) to kCLLocationAccuracyKilometer (1000 m, cell and Wi-Fi), and distanceFilter (default kCLDistanceFilterNone) suppresses updates until the device has moved that far. Continuous high-accuracy updates are among the fastest battery drains, so use them only while the feature is on screen, stop updating when done, and prefer requestLocation() for a single fix.
For background needs, use the system’s low-power services instead of polling. Significant-location-change (startMonitoringSignificantLocationChanges()) wakes or relaunches the app on a large movement (cell-tower scale, hundreds of metres or more), working even after the app was terminated (it needs Always authorization). Visits (startMonitoringVisits()) deliver arrival and departure events at places where the user stays. Region monitoring (geofencing) uses CLCircularRegion (center, radius): the system notifies on entry and exit even if the app is not running, but an app may monitor at most 20 regions at once, so a store locator must monitor the nearest few and swap them as the user moves, and boundaries are fuzzy (accuracy depends on Wi-Fi and cell data, and a small radius is unreliable). Beacons use CLBeaconIdentityConstraint. Geometry is handled for you: CLLocation.distance(from:) gives metres along the great-circle (Pune to Mumbai is about 120 km), region.contains(coordinate) tests membership, and CLLocationCoordinate2DIsValid rejects impossible values such as a latitude of 91. Handle denial gracefully (explain, link to Settings), check horizontalAccuracy (a negative value means invalid) and the timestamp (cached fixes can be old), remember simulators and indoor locations are imprecise, and treat location as sensitive data: collect the minimum, do not log it, and say why. Background location also needs the location background mode.
The great-circle distance is about 120 km. A point a few metres away is inside the 200 m region, Mumbai is not, and a latitude of 91 is not a valid coordinate.
A fresh app is notDetermined (0), Always is 3 and When In Use is 4. Best accuracy and no filter are encoded as −1, and the kilometre accuracy is 1000 metres.
Common traps
- Requesting Always authorization up front. Users refuse it; start with When In Use and escalate when the benefit is clear.
- Leaving high-accuracy updates running in the background. It drains the battery; stop when finished and prefer significant-change or visits.
They might follow up with
- How many regions can an app monitor? 20; monitor the nearest and rotate as the user moves.
- What does a negative
horizontalAccuracymean? The location is invalid.
Related questions
- 17.2.2 How do you show places with MapKit: annotations, overlays, regions and clustering?
- 17.7.1 How do you approach an unfamiliar Apple framework: what do you check before you write code, and how do you…
- 14.3.1 What is a privacy manifest, what are required-reason APIs, and what must third-party SDKs declare?
How do you show places with MapKit: annotations, overlays, regions… →