ThomasMead
ThomasMead

Reputation: 33

Mystified by how EnvironmentObject is being updated (or not)

I have an EnvironmentObject variable that is being used various places.

I would like to update it using a button with a .alert modifier.

The .alert invokes a func within which the EnvironmentObject updates itself with a name supplied by the .alert modifier.

Puzzle is that within the func the EnvironmentObject seems unchanged. On the first use, it shows the initialized values. But when it is used by the Map($...) it does seem to have been updated. Subsequent uses of the button show that the values within the func are always from the last update.

I want to use the EnvironmentObject elsewhere, but it is always one step behind.

here is the code with some comments. If there's another way, please suggest.

import SwiftUI
import MapKit

struct LocationFinderViewCopy: View {
    @EnvironmentObject  var mapAPI: MapAPI  // I am using this elsehwere
    @State private var showingAlert = false
    @State private var locationName = ""
    
    
    
    var body: some View {
        VStack {
            Map(position: $mapAPI.locations[0].cameraPosition) {  //$mapAPI shows the most recent update, despite what I see in the findlocation function
                let temp = mapAPI.locations[0].coordinate
                let tempCam = mapAPI.locations[0].cameraPosition.region
                Annotation(mapAPI.locations[0].name, coordinate:  mapAPI.locations[0].coordinate, anchor: .center) {
                    MapMarkerView()
                }
            }
   
            Button("Alert find Button") {
                showingAlert.toggle()
            }
            .alert("Location for find", isPresented: $showingAlert) {
                TextField("location", text: $locationName)
                Button("Cancel", action: doNothing)
                Button("OK", action: findLocation)
            } message: {
                Label("name", systemImage: "circle.circle")
            }
        }
        
    }
    func doNothing() {
    }
    func findLocation() {
        let tempCoord1 = mapAPI.locations[0].coordinate  // mapAPI original intiation
        let tempCam1 = mapAPI.locations[0].cameraPosition  //checking value
        let name = locationName
        mapAPI.getLocation(address: locationName, delta: 10)
        let tempCoord2 = mapAPI.locations[0].coordinate  // expected mapAPI to reflect it is still showing init values.  Each subsequent entry shows the previous request.  same value as tempCoord1
        let tempCam2 = mapAPI.locations[0].cameraPosition
    }
}

#Preview {
    LocationFinderViewCopy()
}




Trying to update an EnvironmentObject and the updates appear out of sync

Upvotes: 1

Views: 98

Answers (1)

malhal
malhal

Reputation: 30746

It's best to use @Environment for your API and have a function that returns a location you can store in a state, e.g.

@Environment(\.mapAPI) var mapAPI

@State var location: Location
@State var gettingLocation = false

Button(gettingLocation ? "Cancel" : "Get Location") {
    gettingLocation.toggle()
}
.task(id: gettingLocation) {
    if !gettingLocation { return }
    location = await mapAPI.getLocation()
    gettingLocation = false
}

This way you can avoid the inconsistency issue typical of objects.

Upvotes: 0

Related Questions