Reputation: 37579
This is a library that doesn't have a very great documentation, In the past, I had problems migrating from a previous version to a modern version, and now, I have exactly the same problem again. In SwiftLocation 4 this is the way to get the placemark from a location, passing it the coordinates of that location:
SwiftLocation.LocationManager.shared.locateFromCoordinates(location.coordinate) { result in
switch result {
case .success(let places):
guard let receivedPlacemark = places.first?.placemark else {
return
}
logger.debug("Retrieved placemark: (receivedPlacemark.locality ?? "-")")
self?.currentPlacemark = receivedPlacemark
NotificationCenter.default.post(name: Constants.Notifications.placemarkUpdateNotification, object: nil)
case .failure(let error):
logger.error(error.localizedDescription)
NotificationCenter.default.post(name: Constants.Notifications.placemarkUpdateNotification, object: nil)
}
}
Now, after upgrading to 5.1.0 version of SwiftLocation I simply can't find in GitHub or the cocoapods documentation of the library how to do the same with the actual version. SwiftLocation.LocationManager.shared.locateFromCoordinates
doesn't exists and can't find anything similar.
How can I do that with 5.1.0?
Upvotes: 0
Views: 664
Reputation: 1
Had a similar problem and this is what worked for me:
Inside your LocationManager
create an optional CLPlacemark
object:
@Published var placemark: CLPlacemark?
Then, in your didUpdateLocations
func (still inside LocationManager
) create a CLGeoCoder
that uses your users location like so:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.last else { return }
self.userLocation = location
let geoCoder = CLGeocoder()
geoCoder.reverseGeocodeLocation(userLocation!) { placemarks, error in
self.placemark = placemarks?.last
}
}
LocationManager
Code in full:
import CoreLocation
import Foundation
class LocationManager: NSObject, ObservableObject {
static let shared = LocationManager()
private let manager = CLLocationManager()
@Published var userLocation: CLLocation?
@Published var authorizationState: CLAuthorizationStatus?
@Published var placemark: CLPlacemark?
override init() {
super.init()
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
}
func requestLocation() {
manager.requestWhenInUseAuthorization()
}
}
extension LocationManager: CLLocationManagerDelegate {
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
self.authorizationState = manager.authorizationStatus
if manager.authorizationStatus == .authorizedAlways || manager.authorizationStatus == .authorizedWhenInUse {
manager.startUpdatingLocation()
} else if manager.authorizationStatus == .denied {
print("Permission to location was denied")
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.last else { return }
self.userLocation = location
let geoCoder = CLGeocoder()
geoCoder.reverseGeocodeLocation(userLocation!) { placemarks, error in
self.placemark = placemarks?.last
}
}
}
You can use the above to pass in your UI like so:
struct ContentView: View {
@ObservedObject var locationManager = LocationManager.shared
var body: some View {
VStack {
Text(locationManager.placemark?.locality ?? "Unknown Location")
.font(.system(size: 40, design: .rounded)).bold()
}
}
}
Upvotes: 0
Reputation: 376
The process name for what you are trying to achieve is Geocoding.
From what I can see the location API changed a bit, so the code you are looking for is (from documentation):
let service = // insert your service here
SwiftLocation.geocodeWith(service).then { result in
// You will get an array of suggested [GeoLocation] objects with data and coordinates
print(result.data)
}
where service
should equal to your service of choosing, but if we want to use Apple engine to get data for given coordinates, you can try:
let service = Geocoder.Apple(coordinates: location) //location must be CLLocationCoordinate2D
Upvotes: 1