Core Location Diagnostics
Symptom-based troubleshooting for Core Location issues.
When to Use
- Location updates never arrive
- Background location stops working
- Authorization always denied
- Location accuracy unexpectedly poor
- Geofence events not triggering
- Location icon won't go away
Related Skills
axiom-core-location β Implementation patterns, decision trees
axiom-core-location-ref β API reference, code examples
axiom-energy-diag β Battery drain from location
axiom-mapkit-diag β For map-specific location display issues (Symptom 7)
Symptom 1: Location Updates Never Arrive
Quick Checks
let status = CLLocationManager().authorizationStatus
print("Authorization: \(status.rawValue)")
print("Services enabled: \(CLLocationManager.locationServicesEnabled())")
let accuracy = CLLocationManager().accuracyAuthorization
print("Accuracy: \(accuracy == .fullAccuracy ? "full" : "reduced")")
Decision Tree
Q1: What does authorizationStatus return?
ββ .notDetermined β Authorization never requested
β Fix: Add CLServiceSession(authorization: .whenInUse) or requestWhenInUseAuthorization()
β
ββ .denied β User denied access
β Fix: Show UI explaining why location needed, link to Settings
β
ββ .restricted β Parental controls block access
β Fix: Inform user, offer manual location input
β
ββ .authorizedWhenInUse / .authorizedAlways β Check next
Q2: Is locationServicesEnabled() returning true?
ββ NO β Location services disabled system-wide
β Fix: Show UI prompting user to enable in Settings β Privacy β Location Services
β
ββ YES β Check next
Q3: Are you iterating the AsyncSequence?
ββ NO β Updates only arrive when you await
β Fix: Task { for try await update in CLLocationUpdate.liveUpdates() { ... } }
β
ββ YES β Check next
Q4: Is the Task cancelled or broken?
ββ YES β Task cancelled before updates arrived
β Fix: Ensure Task lives long enough (store in property, not local)
β
ββ NO β Check next
Q5: Is location available? (iOS 17+)
ββ Check update.locationUnavailable
β If true: Device cannot determine location (indoors, airplane mode, no GPS)
β Fix: Wait or inform user to move to better location
β
ββ Check update.authorizationDenied / update.authorizationDeniedGlobally
If true: Handle denial gracefully
Info.plist Checklist
<key>NSLocationWhenInUseUsageDescription</key>
<string>Your clear explanation here</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Your clear explanation here</string>
Missing these keys = silent failure with no prompt.
Symptom 2: Background Location Not Working
Quick Checks
- Background mode capability: Xcode β Signing & Capabilities β Background Modes β Location updates
- Info.plist: Should have
UIBackgroundModes with location value
- CLBackgroundActivitySession: Must be created AND held
Decision Tree
Q1: Is "Location updates" checked in Background Modes?
ββ NO β Background location silently disabled
β Fix: Xcode β Signing & Capabilities β Background Modes β Location updates
β
ββ YES β Check next
Q2: Are you holding CLBackgroundActivitySession?
ββ NO / Using local variable β Session deallocates, background stops
β Fix: Store in property: var backgroundSession: CLBackgroundActivitySession?
β
ββ YES β Check next
Q3: Was session started from foreground?
ββ NO β Cannot start new session from background
β Fix: Create CLBackgroundActivitySession while app in foreground
β
ββ YES β Check next
Q4: Is app being terminated and not recovering?
ββ YES β Not recreating session on relaunch
β Fix: In didFinishLaunchingWithOptions:
β if wasTrackingLocation {
β backgroundSession = CLBackgroundActivitySession()
β startLocationUpdates()
β }
β
ββ NO β Check authorization level
Q5: What is authorization level?
ββ .authorizedWhenInUse β This is fine with CLBackgroundActivitySession
β The blue indicator allows background access
β
ββ .authorizedAlways β Should work, check session lifecycle
β
ββ .denied β No background access possible
Common Mistakes
func startTracking() {
let session = CLBackgroundActivitySession()
startLocationUpdates()
}
var backgroundSession: CLBackgroundActivitySession?
func startTracking() {
backgroundSession = CLBackgroundActivitySession()
startLocationUpdates()
}
Symptom 3: Authorization Always Denied
Decision Tree
Q1: Is this a fresh install or returning user?
ββ FRESH INSTALL with immediate denial β Check Info.plist strings
β Missing/empty NSLocationWhenInUseUsageDescription = automatic denial
β
ββ RETURNING USER β Check previous denial
Q2: Did user previously deny?
ββ YES β User must manually re-enable in Settings
β Fix: Show UI explaining value, with button to open Settings:
β UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!)
β
ββ NO β Check next
Q3: Are you requesting authorization at wrong time?
ββ Requesting when app not "in use" β insufficientlyInUse
β Check: update.insufficientlyInUse or diagnostic.insufficientlyInUse
β Fix: Only request authorization from foreground, during user interaction
β
ββ NO β Check next
Q4: Is device in restricted mode?
ββ YES β .restricted status (parental controls, MDM)
β Fix: Cannot override. Offer manual location input.
β
ββ NO β Check Info.plist again
Q5: Are Info.plist strings compelling?
ββ Generic string β Users more likely to deny
β Bad: "This app needs your location"
β Good: "Your location helps us show restaurants within walking distance"
β
ββ Review: Look at string from user's perspective
Info.plist String Best Practices
<key>NSLocationWhenInUseUsageDescription</key>
<string>We need your location.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Your location helps show restaurants, coffee shops, and attractions within walking distance.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>We need your location always.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Enable background location to receive reminders when you arrive at saved places, even when the app is closed.</string>
Symptom 4: Location Accuracy Unexpectedly Poor
Quick Checks
let accuracy = CLLocationManager().accuracyAuthorization
print("Accuracy auth: \(accuracy == .fullAccuracy ? "full" : "reduced")")
for try await update in CLLocationUpdate.liveUpdates() {
if update.accuracyLimited {
print("Accuracy limited - updates every 15-20 min")
}
if let location = update.location {
print("Horizontal accuracy: \(location.horizontalAccuracy)m")
}
}
Decision Tree
Q1: What is accuracyAuthorization?
ββ .reducedAccuracy β User chose approximate location
β Options:
β 1. Accept reduced accuracy (weather, city-level features)
β 2. Request temporary full accuracy:
β CLServiceSession(authorization: .whenInUse, fullAccuracyPurposeKey: "Navigation")
β 3. Explain value and link to Settings
β
ββ .fullAccuracy β Check environment and configuration
Q2: What is horizontalAccuracy on locations?