I have an app where I want to filter an array of objects stored in SwiftData by using filter chips. I have build both components and the chips to update based on a toggle of .onTapGesture inside their FilterChipView. However in my main content view (HomeViewViewController) the list of projects is not updated. It seams like I lose the info somewhere that a filter has been tapped so please update view accordingly.
updated FilterModel:
struct FilterModel: Identifiable {
@State var isFilterTapped: Bool **--> zu var isFilterTapped: Bool**
let id = UUID()
let filterIcon: String
let filterKey: ProjectStatus.Status
}
fixed FilterChipView:
struct FilterChipView: View {
let chipIcon: String
let titleKey: ProjectStatus.Status.RawValue
@**Binding** var isFilterTapped: Bool
var body: some View {
HStack(spacing: 4) {
Image.init(systemName: chipIcon)
.font(.body)
Text(titleKey)
.font(.body)
.lineLimit(1)
}
.padding(.vertical, 4)
.padding(.leading, 4)
.padding(.trailing, 10)
.foregroundColor(isFilterTapped ? .white : Color(UIColor.darkGray))
.background(isFilterTapped ? Color(UIColor.timeVizLightBlue) : Color(UIColor.systemGray6))
.cornerRadius(20)
// .overlay(
// RoundedRectangle(cornerRadius: 20)
// .stroke(Color.blue, lineWidth: 1.5)
//
// )
.onTapGesture {
isFilterTapped.toggle()
}
}
}
FilterChipViewModel:
class FilterViewModel: ObservableObject {
@Published var filters: [FilterModel] = [
FilterModel(isFilterTapped: false, filterIcon: "circle.fill", filterKey: .open),
FilterModel(isFilterTapped: false, filterIcon: "checkmark.circle.fill", filterKey: .done),
FilterModel(isFilterTapped: false, filterIcon: "bolt.circle.fill", filterKey: .released)
]
}
updated & fixed FilterChipContainerView:
struct FilterChipContainerView: View {
@ObservedObject var filterViewModel = FilterViewModel() **--> zu @ObservedObject var filterViewModel: FilterViewModel**
var body: some View {
HStack {
ForEach(**$**filterViewModel.filters) { **$**filter in
FilterChipView(
chipIcon: filter.filterIcon,
titleKey: filter.filterKey.rawValue,
isFilterTapped: **$**filter.isFilterTapped
)
}
}
}
}
ContentView (HomeViewViewController):
struct HomeViewViewController: View {
@Query(sort: \ProjectModel.projectTitle) var projects: [ProjectModel]
@State var selectedStatus: ProjectStatus.Status = .done
@StateObject var filterViewModel = FilterViewModel()
@Environment(\.modelContext) var modelContext
var body: some View {
NavigationStack {
Text("meine Projekte:")
.font(.title)
.foregroundStyle(.black)
.frame(maxWidth: .infinity, alignment: .leading)
.padding()
VStack(alignment: .center, spacing: 16) {
FilterChipContainerView(filterViewModel: filterViewModel)
}
.padding(.horizontal, 16)
List(filterViewModel.filters) { filter in
if filter.isFilterTapped {
Text("Filter gedrücket")
ForEach(projects, id: \.id) { project in
if filter.isFilterTapped && filter.filterKey == project.projectStatus {
ProjectCard(project: project)
}
}
.onDelete(perform: deleteProject)
.listRowSeparator(.hidden)
}
}
.listStyle(.plain)
.listRowBackground(Color.clear)
.listRowSpacing(10)
.safeAreaInset(edge: .bottom) {
AddNewProjectView()
}
}
}
private func deleteProject(_ indexSet: IndexSet) {
for index in indexSet {
let project = projects[index]
modelContext.delete(project)
}
}
}
extension UIApplication {
func endEditing() {
sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
}
#Preview {
HomeViewViewController()
}
When I manually set the filters in the viewModel to "isFilterTapped: true" or false the filters do work. But they do not update / update the List based on selection in app. Any idea how I can fix this?
Thanks a ton in advance I have been trying to get this to work for the past three days without any luck... :/ You shall be my "Ehre-Person" :)
I have tried using @StateObject and @ObservedObject but neither seam to update the contentView when a filter is tapped. This is driving me nuts.. :/