Dwight
Dwight

Reputation: 12470

SwiftUI Maps - Cannot use instance member within property initializer; property initializers run before 'self' is available

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'

Upvotes: 1

Views: 513

Answers (1)

Dwight
Dwight

Reputation: 12470

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)
    }
}

Upvotes: 2

Related Questions