Created
June 6, 2023 21:38
-
-
Save leafonthewind/c2be8cad05861ce710113e61790be12f to your computer and use it in GitHub Desktop.
Dynamically filtering @query with SwiftUI + SwiftData
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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]) | |
} | |
} | |
}) | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Borrowed and adapted from Paul Hudson's excellent Hacking with Swift article: https://www.hackingwithswift.com/books/ios-swiftui/dynamically-filtering-fetchrequest-with-swiftui