Adding MapPin to SwiftUI Tutorial MapView.swift

New guy here, hacking away on the SwiftUI tutorial (https://developer.apple.com/tutorials/swiftui/building-lists-and-navigation ):

In MapView.swift it would be useful to add a pin/marker. Thus adding:

struct Place: Identifiable {
    let id = UUID()
    let name: String
    let coordinate: CLLocationCoordinate2D
}
var annotations = [
    Place(name: "Xyz", coordinate: CLLocationCoordinate2D(latitude: 34.011286, longitude: -116.166868))
]

and modifying the View to:

var body: some View {
    Map(coordinateRegion: $region, annotationItems: annotations) {
        MapPin(coordinate: $0.coordinate)
    }
    .onAppear {
        setRegion(coordinate)
    }
}

puts a pin on the Turtle Rock map using the hard-coded latitude and longitude.

However, changing (latitude: 34.011286, longitude: -116.166868) to (latitude: coordinate.latitude, longitude: coordinate.longitude) results in error "Cannot use instance member 'coordinate' within property initializer; property initializers run before 'self' is available."

What modifications to the project are required to access the latitude and longitude for use in the annotation?

Answered by OOPer in 690823022

So, Place and annotations are declared inside struct MapView and coordinate is a property of MapView. You should better include all such info in the original post. Generally, when you show your code, you should better show the whole file of interest, that helps readers check what's going on.


As the error message is clearly stating, in your code on the line initializing the instance property annotations, you are trying to use another instance property coordinate, which is not permitted in Swift.

One possible solution would be initializing annotations somewhere else than the property initializer.

struct MapView: View {
    var coordinate: CLLocationCoordinate2D
    @State private var region = MKCoordinateRegion()

    struct Place: Identifiable {
        let id = UUID()
        let name: String
        let coordinate: CLLocationCoordinate2D
    }
    @State var annotations: [Place] = [] //<-

    var body: some View {
        Map(coordinateRegion: $region, annotationItems: annotations) {
            MapPin(coordinate: $0.coordinate)
        }
        .onAppear {
            setRegion(coordinate)
            //↓
            annotations = [
                Place(name: "Xyz", coordinate: CLLocationCoordinate2D(latitude: coordinate.latitude, longitude: coordinate.longitude))
            ]
        }
    }
    private func setRegion(_ coordinate: CLLocationCoordinate2D) {
        region = MKCoordinateRegion(
            center: coordinate,
            span: MKCoordinateSpan(latitudeDelta: 0.2, longitudeDelta: 0.2)
        )
    }
}

I cannot reproduce the exact error "Cannot use instance member 'coordinate' within property initializer; property initializers run before 'self' is available.". Can you show enough code (complete and ready to build) to reproduce the issue?

All of the code is in the SwiftUI tutorial at the URL provided above. Start with the BuildingListsAndNavigation.xcodeproj in the Complete folder of the downloaded project. I have just now repeated the changes shown above starting with a new download, with the same results. Note that the addition goes before the View, which is completely replaced.

@rKubischt, if all the code is exactly the same as the tutorial, you would not get that error. You should better show YOUR code.

The complete MapView.swift with all of the changes noted above, which are the only changes to the downloaded project identified above:

import SwiftUI
import MapKit

struct MapView: View {
    var coordinate: CLLocationCoordinate2D
    @State private var region = MKCoordinateRegion()

    struct Place: Identifiable {
        let id = UUID()
        let name: String
        let coordinate: CLLocationCoordinate2D
    }
    var annotations = [
        Place(name: "Xyz", coordinate: CLLocationCoordinate2D(latitude: coordinate.latitude, longitude: coordinate.longitude))
    ]

    var body: some View {
        Map(coordinateRegion: $region, annotationItems: annotations) {
            MapPin(coordinate: $0.coordinate)
        }
        .onAppear {
            setRegion(coordinate)
        }
    }
    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))
    }
}
Accepted Answer

So, Place and annotations are declared inside struct MapView and coordinate is a property of MapView. You should better include all such info in the original post. Generally, when you show your code, you should better show the whole file of interest, that helps readers check what's going on.


As the error message is clearly stating, in your code on the line initializing the instance property annotations, you are trying to use another instance property coordinate, which is not permitted in Swift.

One possible solution would be initializing annotations somewhere else than the property initializer.

struct MapView: View {
    var coordinate: CLLocationCoordinate2D
    @State private var region = MKCoordinateRegion()

    struct Place: Identifiable {
        let id = UUID()
        let name: String
        let coordinate: CLLocationCoordinate2D
    }
    @State var annotations: [Place] = [] //<-

    var body: some View {
        Map(coordinateRegion: $region, annotationItems: annotations) {
            MapPin(coordinate: $0.coordinate)
        }
        .onAppear {
            setRegion(coordinate)
            //↓
            annotations = [
                Place(name: "Xyz", coordinate: CLLocationCoordinate2D(latitude: coordinate.latitude, longitude: coordinate.longitude))
            ]
        }
    }
    private func setRegion(_ coordinate: CLLocationCoordinate2D) {
        region = MKCoordinateRegion(
            center: coordinate,
            span: MKCoordinateSpan(latitudeDelta: 0.2, longitudeDelta: 0.2)
        )
    }
}
Adding MapPin to SwiftUI Tutorial MapView.swift
 
 
Q