A simple implementation of CLLocationManager. Works in the foreground and background. Displays location on MKMapView. Tapping location on map displays address using reverse geocoding.
let locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.requestAlwaysAuthorization()
extension ViewController: CLLocationManagerDelegate {
/// Receives user response to monitor location
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
guard status == .authorizedAlways || status == .authorizedWhenInUse else { return }
locationManager.startUpdatingLocation()
locationManager.allowsBackgroundLocationUpdates = status == .authorizedAlways ? true : false
}
/// Receives location information
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.last else { return }
display(location: location)
}
}
private func reverseGeocode(location: CLLocation) {
CLGeocoder().reverseGeocodeLocation(location, completionHandler: { [unowned self] placemark, error in
guard let p = placemark?.first else { self.setAnnotation(subtitle: nil, location: location); return }
// Address Example: 12345 Elm Street, Tampa, FL 33660, United States
let address = "\(p.subThoroughfare ?? "") \(p.thoroughfare ?? "Unknown"), \(p.locality ?? ""), \(p.administrativeArea ?? "") \(p.postalCode ?? ""), \(p.country ?? "")."
self.setAnnotation(subtitle: address, location: location)
})
}
private func setAnnotation(subtitle: String?, location: CLLocation) {
let annotation = MKPointAnnotation()
annotation.coordinate = location.coordinate
annotation.title = "Current Location"
annotation.subtitle = subtitle
map.addAnnotation(annotation)
}