Skip to content

Instantly share code, notes, and snippets.

@leafonthewind
Created June 6, 2023 21:38
Show Gist options
  • Save leafonthewind/c2be8cad05861ce710113e61790be12f to your computer and use it in GitHub Desktop.
Save leafonthewind/c2be8cad05861ce710113e61790be12f to your computer and use it in GitHub Desktop.
Dynamically filtering @query with SwiftUI + SwiftData
//
// ContentView.swift
// SwiftDataTest
//
// Created by Matthew Edwards on 6/6/23.
//
import SwiftUI
import SwiftData
struct ContentView: View {
@Environment(\.modelContext) private var modelContext
@State private var lastNameFilter = ""
var body: some View {
VStack {
FilteredList(filter: lastNameFilter)
Button("Add Examples") {
let singerArray: [Singer] = [
Singer(firstName: "Taylor", lastName: "Swift"),
Singer(firstName: "Ed", lastName: "Sheeran"),
Singer(firstName: "Adele", lastName: "Adkins")
]
for singer in singerArray {
modelContext.insert(singer)
}
}
Button("Show Adele") {
lastNameFilter = "Adkins"
}
Button("Show Taylor") {
lastNameFilter = "Swi"
}
Button("Show All") {
lastNameFilter = ""
}
}
}
private func addSingers() {
let singerArray: [Singer] = [
Singer(firstName: "Taylor", lastName: "Swift"),
Singer(firstName: "Ed", lastName: "Sheeran"),
Singer(firstName: "Adele", lastName: "Adkins")
]
for singer in singerArray {
modelContext.insert(singer)
}
}
}
#Preview {
ContentView()
.modelContainer(for: Singer.self, inMemory: true)
}
//
// FilteredList.swift
// SwiftDataTest
//
// Created by Matthew Edwards on 6/6/23.
//
import SwiftUI
import SwiftData
struct FilteredList: View {
@Environment(\.modelContext) private var modelContext
@Query private var singers: [Singer]
init(filter: String) {
if filter.isEmpty {
_singers = Query(filter: #Predicate<Singer> { $0.lastName.count > 0 },
sort: \.lastName,
order: .forward,
animation: .spring)
} else {
_singers = Query(filter: #Predicate<Singer> { $0.lastName.contains(filter) },
sort: \.lastName,
order: .forward,
animation: .spring)
}
}
var body: some View {
List {
ForEach(singers, id: \.self) { singer in
Text("\(singer.firstName) \(singer.lastName)")
}
.onDelete(perform: { indexSet in
withAnimation {
for index in indexSet {
modelContext.delete(singers[index])
}
}
})
}
}
}
//
// Singer.swift
// SwiftDataTest
//
// Created by Matthew Edwards on 6/6/23.
//
import Foundation
import SwiftData
@Model
final class Singer {
var firstName: String
var lastName: String
init(firstName: String, lastName: String) {
self.firstName = firstName
self.lastName = lastName
}
}
@leafonthewind
Copy link
Author

Borrowed and adapted from Paul Hudson's excellent Hacking with Swift article: https://www.hackingwithswift.com/books/ios-swiftui/dynamically-filtering-fetchrequest-with-swiftui

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment