Subject
I’m encountering a difficulty in SwiftUI the place modifying a value-type mannequin inside a baby view typically causes the navigation stack to pop unexpectedly. This occurs though I am solely modifying a property contained in the youngster view, not changing the whole mannequin.
Context
I’ve an inventory of things in a NavigationStack, the place choosing an merchandise navigates to a element view. The element view permits enhancing the title property through a TextField.
Right here’s the simplified code:
import SwiftUI
struct Merchandise: Identifiable, Hashable {
let id: UUID
var title: String
}
struct ContentView: View {
@State non-public var objects = [
Item(id: UUID(), name: "Item 1"),
Item(id: UUID(), name: "Item 2")
]
var physique: some View {
NavigationStack {
Listing($objects) { $merchandise in
NavigationLink(merchandise.title, worth: merchandise)
}
.navigationDestination(for: Merchandise.self) { merchandise in
DetailView(merchandise: merchandise)
}
}
}
}
struct DetailView: View {
@State var merchandise: Merchandise // <- Native copy of the merchandise
var physique: some View {
VStack {
TextField("Edit Title", textual content: $merchandise.title)
.textFieldStyle(.roundedBorder)
.padding()
}
.navigationTitle(merchandise.title)
}
}
Drawback
Once I sort within the TextField, the view typically pops again to the earlier display with out urgent the again button. It looks like the navigation stack is shedding monitor of my Merchandise occasion when its title is up to date.
- Used @Binding in DetailView
- Modified DetailView to just accept a @Binding var merchandise: Merchandise as a substitute of utilizing @State.
- This prompted a compiler error as a result of NavigationDestination passes a copied worth, not a binding.
- Wrapped Merchandise in a Reference Kind (class)
- Transformed Merchandise from a struct to a category and used @ObservableObject.
- This fastened the navigation pop subject however launched issues with Codable, Hashable, and thread security.
- Tracked the Chosen Merchandise Individually
-
Launched an express @State non-public var selectedItem: Merchandise? in ContentView.
-
Manually assigned the chosen merchandise earlier than navigation.
-
This labored however felt like a hack moderately than a SwiftUI-friendly strategy.
-
Anticipated Habits
Updating merchandise.title inside DetailView ought to solely replace that subject and never trigger SwiftUI to pop the navigation stack. -
Precise Habits
Altering merchandise.title typically causes the view to pop unexpectedly, as if SwiftUI misplaced monitor of the navigation state.