How do I dynamically add pins and other annotations to the new SwiftUI Map view for iOS 14

I already know how to set up map pins or annotations like discussed here: https://developer.apple.com/forums/thread/651668

But the real question is:
How do I replace the hardcoded location data with passed parameters?

This Code is executed without problems, due to the fact that the coords in locations are hardcoded:

Code Block import SwiftUI
import MapKit
struct Location: Identifiable {
    let id = UUID()
    let name: String
    let latitude: Double
    let longitude: Double
    var coordinate: CLLocationCoordinate2D {
        CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
    }
}
struct MapView: View {
    let locations = [Location(name: "Turtle Rock", latitude: 34.011_286, longitude: -116.166_868)]
    var coordinate: CLLocationCoordinate2D
    var lat: Double
    var long: Double
    @State private var region = MKCoordinateRegion()
    var body: some View {
        Map(coordinateRegion: $region,showsUserLocation: true, annotationItems: locations){ loco in
            MapPin(coordinate: loco.coordinate)
        }
        .onAppear{
            setRegion(coordinate)
        }   .edgesIgnoringSafeArea(.all)
    }
    private func setRegion(_ coordinate: CLLocationCoordinate2D){
        region = MKCoordinateRegion(
            center: coordinate,
            span: MKCoordinateSpan(latitudeDelta: 0.2, longitudeDelta: 0.2)
        )
    }
}
struct MapView_Previews: PreviewProvider {
    static var previews: some View {
        MapView(coordinate: CLLocationCoordinate2D(latitude: 34.011_286, longitude: -116.166_868),lat: 34.011_286, long: -116.166_868)
    }
}


But as soon as I try to use lat(itude) or long(itude) or even coordinate from the passed parameters, I have to use lazy vars and therefore cannot access that mutable getters... any advice?

Code Block
let locations = [Location(name: "Turtle Rock", latitude: lat, longitude: long)]
//this Throws: Cannot use instance member 'lat' within property initializer; property initializers run before 'self' is available.
//Using lazy var results in: Cannot use mutating getter on immutable value: 'self' is immutable




I'm attempting to do the same thing (I think). The equivalent of dropping a pin in a Map() with a longpress gesture in SwiftUI. My hope is that the user can create an object that is an annotationItem.

Were you able to figure this out?

Thanks.
  • -Kurt

Accepted Answer

The code you have shared attempts to dynamically provide a latitude and a longitude for the hard coded place "Turtle Rock". I think what you actually want to achieve, is to dynamically provide one or many locations to your MapView.

So rather than passing a lat and a long, and hard coding a locations array of a single "Turtle Rock" Location within your MapView, you want to pass an array of Location structs to the MapView initializer.

You can achieve this by changing the locations property to a var instead of a let and pass in the array of Locations in the initializer instead of the lat and long your code currently uses.

How do I dynamically add pins and other annotations to the new SwiftUI Map view for iOS 14
 
 
Q