1

I'm trying to use MapKit's Map with SwiftUI and dynamic latitude/longitude values that are passed into the view by the parent view on the navigation stack. All the MapKit documentation for Swift indicates you need to use @State with MKCoordinateRegion but always uses it with constant latitude/longitude values.

struct PlaceDetail: View {
    let place: Place
    
    @State private var region = MKCoordinateRegion(
        center: CLLocationCoordinate2D(latitude: place.latitude, longitude: place.longitude),
        latitudinalMeters: 750,
        longitudinalMeters: 750
    )
    
    var body: some View {
        Map(coordinateRegion: region)
    }
}

I want to be able to use this dynamically with the latitude/longitude values provided by the place object passed in by the parent view. The above code results in an compiler errors:

Cannot use instance member 'place' within property initializer; property initializers run before 'self' is available

What's the cleanest/most updated way to get this view to compile and work as expected?


Edit: I have tried using an initializer but end up with another error relating to assigning against state:

struct PlaceDetail: View {
    let place: Place
    
    @State var region: MKCoordinateRegion
    
    init(place: Place) {
        self.place = place
        
        let region = MKCoordinateRegion(
            center: CLLocationCoordinate2D(latitude: place.latitude, longitude: place.longitude),
            latitudinalMeters: 750,
            longitudinalMeters: 750
        )
        
        self.region = State(initialValue: region)
    }
    
    var body: some View {
        Map(coordinateRegion: $region)
    }
}

Results in:

Cannot assign value of type 'State<MKCoordinateRegion>' to type 'MKCoordinateRegion'

Dwight
  • 12,120
  • 6
  • 51
  • 64
  • 1
    Does this answer your question? [How do I set an @State variable programmatically in SwiftUI](https://stackoverflow.com/questions/56591837/how-do-i-set-an-state-variable-programmatically-in-swiftui) – Andrew Dec 27 '21 at 14:34

1 Answers1

1

I was close in the final edit, but I needed to assign the value _region - not the prefixed underscore. It looks like this is a private setter which is why you need to wrap the value in State. And not forget to use the $ prefix to use the instance variable in the view.

struct PlaceDetail: View {
    let place: Place
    
    @State var region: MKCoordinateRegion
    
    init(place: Place) {
        self.place = place
        
        let region = MKCoordinateRegion(
            center: CLLocationCoordinate2D(latitude: place.latitude, longitude: place.longitude),
            latitudinalMeters: 750,
            longitudinalMeters: 750
        )
        
        self._region = State(initialValue: region)
    }
    
    var body: some View {
        Map(coordinateRegion: $region)
    }
}

Dwight
  • 12,120
  • 6
  • 51
  • 64