Observable Geocoder
Firstly we want to import CoreLocation
for the location services.
We're going to construct a basic class, which subclasses ObservableObject
.
class Geocoder: ObservableObject {
/// ...
}
We're going to add @Published public var
(published public variables),
for the items we want to expose, in my case it are the following variables placeMark
, location
, name
, iso
, country
, postalCode
, state
, subState
, city
, subCity
, street
, subStreet
, region
, timeZone
, inlandWater
, ocean
and areasOfInterest
.
Full Code:
import CoreLocation
class Geocoder: ObservableObject {
/// Placemark
@Published public var placeMark: CLPlacemark?
/// Location
@Published public var location: CLLocation?
/// The name of the placemark.
@Published public var name: String?
/// The abbreviated country or region name.
@Published public var iso: String?
/// The name of the country or region associated with the placemark.
@Published public var country: String?
/// The postal code associated with the placemark.
@Published public var postalCode: String?
/// The state or province associated with the placemark.
@Published public var state: String?
/// Additional administrative area information for the placemark.
@Published public var subState: String?
/// The city associated with the placemark.
@Published public var city: String?
/// Additional city-level information for the placemark.
@Published public var subCity: String?
/// The street address associated with the placemark.
@Published public var street: String?
/// Additional street-level information for the placemark.
@Published public var subStreet: String?
/// The geographic region associated with the placemark.
@Published public var region: CLRegion?
/// The time zone associated with the placemark.
@Published public var timeZone: TimeZone?
/// The name of the inland water body associated with the placemark.
@Published public var inlandWater: String?
/// The name of the ocean associated with the placemark.
@Published public var ocean: String?
/// The relevant areas of interest associated with the placemark.
@Published public var areasOfInterest: [String]?
/// Geocoder
private let geoCoder = CLGeocoder()
init () { }
/// Update to location
func update (to location: CLLocation) {
geoCoder.reverseGeocodeLocation(
location,
completionHandler: { (placemarks, _) -> Void in
// We're only using the first place mark.
if let placeMark = placemarks?[0] {
self.placeMark = placeMark
self.location = placeMark.location
self.name = placeMark.name
self.iso = placeMark.isoCountryCode
self.country = placeMark.country
self.postalCode = placeMark.postalCode
self.state = placeMark.administrativeArea
self.subState = placeMark.subAdministrativeArea
self.city = placeMark.locality
self.subCity = placeMark.subLocality
self.street = placeMark.thoroughfare
self.subStreet = placeMark.subThoroughfare
self.region = placeMark.region
self.timeZone = placeMark.timeZone
self.inlandWater = placeMark.inlandWater
self.ocean = placeMark.ocean
self.areasOfInterest = placeMark.areasOfInterest
// Send a notification that our `@Published` values have been changed.
self.objectWillChange.send()
}
}
)
}
}
Usage
geocoder.update(to: .init(
latitude: annotation.coordinate.latitude,
longitude: annotation.coordinate.longitude
))
Read more
- self, Self, and Self.self in Swift • 3 minutes reading time.
- Safari in SwiftUI • 2 minutes reading time.
- Safely unwrap optional values in SwiftUI bindings • 4 minutes reading time.
Share
Share Mastodon Twitter LinkedIn Facebook