I have a view to add a new Inventory object. to do so it requires that you select a Vessel object from a picker that it's assigned to. If no Vessels have been created yet, it prompts you to bring up a sheet to add a Vessel first, then dismisses the sheet once the Vessel is added.
If I run this and a Vessel is already existing, everything runs as expected. However, in the case where there are not yet any Vessels to select from, it brings up VesselNewView() on a sheet, and correctly adds a new object to the Vessel class. When it returns to the NewInventorySheet it now shows the picker with the added Vessel checked. Except it isn't. If I print("vessel= \(vessel)")
at this point I get vessel = <Vessel: 0x6000017d07c0> (entity: <null>; id: (null); data: <fault>)
and trying to save crashes the app.
However if I click on the picker and re-select the item that looks like its already selected, then it works fine. How can I force the NewInventoryView to refresh the picker choices for vessel once it returns from adding one on NewVesselView?
Here's my code:
import SwiftUI
struct InventoryNewView: View {
@Environment(\.managedObjectContext) private var viewContext
@State private var showSheetVessel = false
@FetchRequest(
sortDescriptors: [SortDescriptor(\.name)])
var vessels:FetchedResults<Vessel>
@Environment(\.dismiss) var dismiss
@State var name = ""
@State var vessel = Vessel()
var body: some View {
NavigationView {
ScrollView {
VStack(alignment: .leading){
Grid(alignment: .leading) {
GridRow {
Text("Name:")
TextField("Inventory item", text: $name)
}
.padding(.bottom, 5)
GridRow {
Text("Assigned to:")
if vessels.isEmpty == false {
Picker("", selection: $vessel) {
ForEach(vessels) { (vessel: Vessel) in
Text(vessel.name)
.tag(vessel)
}
}
}
else {
Text("Add Vessel")
.fontWeight(.semibold)
.foregroundColor(Color.red)
}
Button(action: {
self.showSheetVessel.toggle()
}) {
Image(systemName: "plus.circle")
.font(.footnote)
}.sheet(isPresented: $showSheetVessel) {
VesselNewView()
}
}
.padding(.bottom, 5)
}
}
.navigationTitle("Add New Inventory")
.navigationBarItems(
trailing:
Button("Add") {
addInventory()
dismiss()
}
.disabled(name.isEmpty)
)
}
}
func addInventory() {
// Add the item into Core Data
let inventory = Inventory(context: viewContext)
inventory.id = UUID()
inventory.name = name
inventory.vessel = vessel
vessel.addToInventory(inventory)
do {
try viewContext.save()
}
catch {
}
}
}
}
To update the selected vessel
, add
.onChange(of: vessels.last) {
if let vesl = vessels.last {
vessel = vesl
}
}
to the NavigationView{...}
.
Note that NavigationView
is deprecated, you should use NavigationStack
.