I have an app that allows entry of transactions with location information that is saved to CoreData. Tapping on the History tab displays a list of transactions and tapping on a single transaction displays detailed transaction information with a map and abbreviated address that the user typed in such as Folsom, CA USA.
If the user would like to edit the location he may tap Edit location and enter a new address. Tapping Save returns to the transaction detail screen where the text location correctly changes to the new location but the map remains at the old location. Exiting the transaction detail screen and then selecting transaction detail again then shows the correct location on the map.
So I believe the map coordinates and text address are being correctly stored in CoreData. It appears that view update (refresh) is not occurring with the map in DetailView.
Below is the call from History to DetailView:
struct ShowHistoryRow: View {
var g: GeometryProxy
@ObservedObject var item: CurrTrans
var body: some View {
NavigationLink(destination: DetailView(item: item)) {
Start of detail view:
// Show transaction details
struct DetailView: View {
// var item: CurrTrans
@ObservedObject var item: CurrTrans // use to refresh view
var coordinate: CLLocationCoordinate2D {
CLLocationCoordinate2D(
latitude: item.entryLat,
longitude: item.entryLong)
}
@State private var mapType: MKMapType = .standard
var body: some View {
GeometryReader { g in
// iPhone portrait mode?
if g.size.height > g.size.width {
PortDetailView(g: g, item: item, coordinate: coordinate, mapType: $mapType)
} else { // landscape
LandDetailView(g: g, item: item, coordinate: coordinate, mapType: $mapType)
}
}
}
call to Edit Location:
struct PortDetailView: View {
var g: GeometryProxy
var item: CurrTrans
var coordinate: CLLocationCoordinate2D
@Binding var mapType: MKMapType
var body: some View {
GeometryReader { g in
VStack {
// location services disabled?
if item.entryLat != 0.0 && item.entryLong != 0.0 {
ShowMap(item: item, coordinate: coordinate, mapType: mapType)
.frame(width: g.size.width, height: g.size.height * 0.68)
.padding(.bottom, 5)
Picker("", selection: $mapType) {
Text("Default").tag(MKMapType.standard)
Text("Transit").tag(MKMapType.hybrid)
Text("Satellite").tag(MKMapType.satellite)
}
.pickerStyle(SegmentedPickerStyle())
.font(.largeTitle)
} else {
VStack {
Text("Map Not Available")
.font(.title2)
.fontWeight(.bold)
Text("Location Services Disabled or Map Not Available")
.font(.subheadline)
}
}
ShowEntryDetails(g: g, item: item)
.padding(.bottom, g.size.height * -0.05)
NavigationLink(destination: EditLocation(g: g, item: item)) {Text("Edit Location")}
}
.font(.subheadline)
.navigationBarTitle("Transaction Details", displayMode: .inline)
.navigationViewStyle(StackNavigationViewStyle())
}
}
}
// Allow change in transaction location
struct EditLocation: View {
var g: GeometryProxy
var item: CurrTrans
@ObservedObject private var lm = LocationManager()
@Environment(\.dismiss) var dismiss
// persistant entry storage in coreData
@Environment(\.managedObjectContext) var viewContext
@State private var getStreet: String = ""
@State private var getCity: String = ""
@State private var getState: String = ""
@State private var getCountry: String = ""
@State private var invalidAddr: Bool = false
var body: some View {
VStack {
ShowEntryDetails(g: g, item: item)
.padding(.top, g.size.height > g.size.width ? g.size.height * 0.05 : 5)
ZStack {
GetFormEntry( getStreet: $getStreet, getCity: $getCity, getState: $getState, getCountry: $getCountry)
.frame(width: g.size.height > g.size.width ? g.size.width * 0.95: g.size.width * 0.75)
} .navigationBarTitle(Text("Edit Transaction Location"), displayMode: .inline) // end zstack
.navigationBarItems(trailing: Button(action: {
// prep address string for conversion to coordinates
let locStr = getStreet + "," + getCity + "," + getState + " " + getCountry
lm.getCoordinate(addressString: locStr) { coordinates, error in
print("edit coordiantes = \(coordinates)")
if error == nil {
print(coordinates.latitude)
print(coordinates.longitude)
item.entryLat = coordinates.latitude
item.entryLong = coordinates.longitude
//item.address = getStreet + "\n" + getCity + " " + getState + "\n" + getCountry
item.entryCity = getCity
item.entryState = getState
item.entryCountry = getCountry
do {
try viewContext.save()
} catch {
print(error.localizedDescription)
}
dismiss()
} else {
// Invalid address-- try again
invalidAddr = true
getStreet = ""
getCity = ""
getState = ""
getCountry = ""
}
}
}) {
Text ("Save")
}.disabled(getStreet.isEmpty || getCity.isEmpty || getCountry.isEmpty)
)
}
.alert("Invalid Address, Try Again", isPresented: $invalidAddr, actions: {
})
}
}