Watched Paul Hudson long SwiftData Tutorial and wanted to modify it by putting in the built-in ContentUnavailableView.search
“No Search Results” view and also a custom “ContentUnavailableView” when there are no physical records/objects in SwiftData Person class to start. This custom View has an "add" button.
Got it working by using a computed property private var allPeople: Int
that gives me the count and then if-else to make the decision. Is there another or better way of grabbing this "Person" count and is this the proper way to branch based on this count using .onAppear? I have seen .overlay used but wasn't sure which was the proper design method.
Whatever I use to keep track of the count in ContentView, I need to send into PeopleView so I can update the count if I delete someone in there.
Still learning and thanks,
Scott
struct ContentView: View {
@Environment(\.modelContext) var modelContext
@State private var destPath = NavigationPath()
@State private var sortOrder = [SortDescriptor(\Person.name)]
@State private var searchText = ""
// Current "Person" count
@State private var personCount = 0
// TEST - Finding the total object count for Person and see if I could keep it updated in this view
private var allPeople: Int {
let decriptor = FetchDescriptor<Person>(predicate: #Predicate { !$0.name.isEmpty })
return (try? modelContext.fetchCount(decriptor)) ?? 0
}
var body: some View {
NavigationStack(path: $destPath) {
Group {
if personCount > 0 {
PeopleView(searchString: searchText, weHavePeople: $personCount, sortOrder: sortOrder)
.navigationTitle("Face Facts Man: \(personCount)")
.toolbar {
Menu("Sort", systemImage: "arrow.up.arrow.down") {
Picker("Sort", selection: $sortOrder) {
"
"
}
}
Button("Add Person", systemImage: "plus", action: addPerson)
}
.searchable(text: $searchText, prompt: "Find Some People...")
} else {
ContentUnavailableView(label: {
Label("You Must Know Someone", systemImage: "list.bullet.rectangle.portrait")
}, description: {
Text("ContentView: Go ahead, add some people! \(personCount)")
}, actions: {
Button("Add A Person", systemImage: "person.badge.plus", action: addPerson)
.buttonStyle(.borderedProminent)
})
}
}
.navigationDestination(for: Person.self) { chosenPerson in
EditPersonView(person: chosenPerson, navPath: $destPath)
}
// TEST: Put in to see if the count was updating and assign so that we can branch above in Group
.onAppear {
personCount = allPeople
}
}
}
/*
Creates the new person and inserts it as "blank" into context. Then change the destPath
to the correct Person we are going to edit. It's now binded and auto-saving is now done as
fields are changed on edit screen.
*/
func addPerson() {
let newPerson = Person(name: "", emailAddress: "", details: "")
modelContext.insert(newPerson)
destPath.append(newPerson)
}
}