Currently, my code finds nearby parks around the user's current location and outputs the name/location in the console fine (using Google Maps & Google Places API). Console Output. The next step I'm trying to complete in my app is to annotate each one of these parks on the map with a marker in the GoogleMapsView.swift file before I return the mapView. My issue is that I can't figure out how to do this after the park locations are found. So my question is how can I observe the park location changes in the array to be able to mark them on the map afterwards? Here is the code I have. In my ContentView.swift, I simply pass the GoogleMapsView into view.
PlacesManager.swift:
import GooglePlaces
class PlacesManager: NSObject, ObservableObject, LocationManagerDelegate {
@Published var places = [Place]()
lazy var googleClient: GoogleClientRequest = GoogleClient()
var locationManager: LocationManager?
var searchRadius : Int = 700
override init() {
super.init()
load()
}
func load() {
locationManager = LocationManager()
locationManager?.delegate = self
}
func locationDidChange(location: CLLocation) {
let lat = location.coordinate.latitude
let long = location.coordinate.longitude
let newLocation: CLLocation = CLLocation(latitude: lat, longitude: long)
fetchGoogleData(forLocation: newLocation, searchRadius: 700)
}
func fetchGoogleData(forLocation: CLLocation, searchRadius: Int) {
//guard let location = currentLocation else { return }
googleClient.getGooglePlacesData(location: forLocation, withinMeters: searchRadius) { (response) in
self.places = response.results
}
}
//... print parks in console code is here
}
LocationManager.swift:
protocol LocationManagerDelegate: class {
func locationDidChange(location: CLLocation)
}
class LocationManager: NSObject, ObservableObject {
weak var delegate: LocationManagerDelegate?
private let locationManager = CLLocationManager()
@Published var location: CLLocation? {
willSet { objectWillChange.send() }
}
var latitude: CLLocationDegrees {
return location?.coordinate.latitude ?? 0
}
var longitude: CLLocationDegrees {
return location?.coordinate.longitude ?? 0
}
override init() {
super.init()
let status = CLLocationManager.authorizationStatus()
if status == .notDetermined {
locationManager.requestWhenInUseAuthorization()
}
if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.startUpdatingLocation()
}
}
}
extension LocationManager: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager,didChangeAuthorization status: CLAuthorizationStatus) {
guard status == .authorizedWhenInUse else {
return
}
locationManager.requestLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.first else {
return
}
self.location = location
self.delegate?.locationDidChange(location: location)
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print(error)
}
}
GoogleMapsView.swift:
struct GoogleMapsView: UIViewRepresentable {
@ObservedObject var locationManager = LocationManager()
@ObservedObject var place: PlacesManager = PlacesManager()
func makeUIView(context: Self.Context) -> GMSMapView {
let camera = GMSCameraPosition.camera(withLatitude: locationManager.latitude, longitude: locationManager.longitude, zoom: 15)
let mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
mapView.isMyLocationEnabled = true
mapView.settings.rotateGestures = false
mapView.settings.tiltGestures = false
mapView.isIndoorEnabled = false
mapView.isTrafficEnabled = false
mapView.isBuildingsEnabled = false
mapView.settings.myLocationButton = true
return mapView
}
}
In my project I used UIKit to handle the map and marker, the approach is quite different from what you posted. Anyway here is one of the function I used to "refresh" the map after I updated the marker from the Place API, hope it helps~