I have this Store
struct, which is a wrapper for all my data. It has a subscript operator which takes in a UUID
, and returns the associated object.
This way, I can have a List
bind to a selection variable, which has type UUID
, and then in another view I can access the selected object from that UUID
.
However, I'm experiencing an issue where my TextField
which binds to the Store
doesn't update. It does update if I wrap it in another Binding
, or if I instead just use Text
.
Here is an minimal reproducible example:
struct Person: Identifiable, Hashable {
let id = UUID()
var name: String
}
struct Store {
var data: [Person]
subscript(id: Person.ID) -> Person {
get {
data.first(where: { $0.id == id })!
}
set {
data[data.firstIndex(where: { $0.id == id })!] = newValue
}
}
}
struct ContentView: View {
@State var store = Store(data: [
Person(name: "Joe"),
Person(name: "Eva"),
Person(name: "Sam"),
Person(name: "Mary")
])
@State var selection: Person.ID?
var body: some View {
NavigationView {
List(store.data, selection: $selection) {
Text($0.name)
}
if let selection = selection {
// Creating a new Binding which simply wraps $store[selection].name
// fixes this issue. Or just using Text also works.
TextField("Placeholder", text: $store[selection].name)
}
else {
Text("No Selection")
}
}
}
}
To reproduce this issue, just click different names on the Sidebar. For some reason the detail view's TextField
doesn't update!
This issue can also be resolved if we simply move the Store
to a ObservableObject
class with @Published
.
Also, making the Store
conform to Hashable
doesn't help this issue.
I feel like I'm missing something very basic with SwiftUI
. Is there any way to fix this?
CodePudding user response:
try this:
TextField("Placeholder", text: $store[selection].name)
.id(selection) // <-- here