The problem is that person is never observed. The Text view in the list will not be notified when the person's name changes because it is not observed.
To fix the problem, create another view that observes the class (ObservableObject). That entire view is invalidated when the @Published field in the @ObservedObject changes.
The code below fixes the problem and the sidebar is correctly updated in real time as the name is edited.
class Person: NSObject, ObservableObject {
@Published public var name: String
init(name: String) {
self.name = name
}
}
class Database {
public var people: [Person]
init() {
people = [Person(name: "Susan"), Person(name: "John"),
Person(name: "Jack"), Person(name: "Mary")]
}
}
@main
struct BindingTestApp: App {
@State private var database = Database()
var body: some Scene {
WindowGroup {
ContentView(people: $database.people)
}
}
}
struct PersonView: View {
@ObservedObject var person: Person
var body: some View {
Text(person.name)
}
}
struct ContentView: View {
struct SidebarView: View {
@Binding var people: [Person]
@Binding var selectedPerson: Person?
var body: some View {
List(people, id: \.self, selection: $selectedPerson) { person in
PersonView(person: person)
}.listStyle(SidebarListStyle())
}
}
struct PersonView: View {
@ObservedObject public var person: Person
var body: some View {
TextField("Name", text: $person.name)
}
}
@Binding var people: [Person]
@State private var selectedPerson: Person?
var body: some View {
NavigationView {
SidebarView(people: $people, selectedPerson: $selectedPerson)
if let selectedPerson = selectedPerson {
PersonView(person: selectedPerson)
} else {
Text("Please select or create a person.")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
@State static private var database = Database()
static var previews: some View {
ContentView(people: $database.people)
}
}
Topic:
UI Frameworks
SubTopic:
SwiftUI
Tags: