-
Notifications
You must be signed in to change notification settings - Fork 140
Expand file tree
/
Copy pathSectionedQuery.swift
More file actions
131 lines (122 loc) · 3.67 KB
/
Copy pathSectionedQuery.swift
File metadata and controls
131 lines (122 loc) · 3.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import SQLiteData
import SwiftUI
struct SectionedQueryDemo: SwiftUICaseStudy {
let readMe = """
This demonstrates how to group the results of a `@FetchAll` query into sections by providing \
a `sectionBy:` argument.
Use the picker to change how the reminders are sectioned: by category, by priority, or with \
no sectioning at all. When grouping by priority, the section of reminders with no priority \
are ordered to the bottom of the list.
"""
let caseStudyTitle = "Sectioned Queries"
@FetchAll(Reminder.none) private var reminders
@State private var sectioning = Sectioning.category
@Dependency(\.defaultDatabase) var database
private enum Sectioning: String, CaseIterable {
case none = "None"
case category = "Category"
case priority = "Priority"
}
var body: some View {
List {
Section {
Picker("Section by", selection: $sectioning) {
ForEach(Sectioning.allCases, id: \.self) { sectioning in
Text(sectioning.rawValue)
}
}
.pickerStyle(.segmented)
}
ForEach($reminders.sections) { section in
Section {
ForEach(section) { reminder in
Text(reminder.title)
}
.onDelete { indices in
withErrorReporting {
try database.write { db in
let ids = indices.map { section[$0].id }
try Reminder
.where { $0.id.in(ids) }
.delete()
.execute(db)
}
}
}
} header: {
if sectioning != .none {
Text(section.name ?? "None")
}
}
}
}
.task(id: sectioning) {
await withErrorReporting {
_ = try await $reminders.load(
Reminder.order(by: \.title),
sectionBy: {
switch sectioning {
case .none:
nil
case .category:
$0.category
case .priority:
$0.priority.asc(nulls: .last)
}
},
animation: .default
)
}
}
}
}
@Table
nonisolated private struct Reminder: Identifiable {
let id: Int
var title: String
var category: String
var priority: String?
}
extension DatabaseWriter where Self == DatabaseQueue {
static var sectionedQueryDatabase: Self {
let databaseQueue = try! DatabaseQueue()
var migrator = DatabaseMigrator()
migrator.registerMigration("Create 'reminders' table") { db in
try #sql(
"""
CREATE TABLE "reminders" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
"title" TEXT NOT NULL,
"category" TEXT NOT NULL,
"priority" TEXT
) STRICT
"""
)
.execute(db)
}
migrator.registerMigration("Seed 'reminders' table") { db in
try Reminder.insert {
Reminder.Draft(title: "Call mom", category: "Family", priority: "High")
Reminder.Draft(title: "Plan vacation", category: "Family")
Reminder.Draft(title: "Buy groceries", category: "Personal", priority: "High")
Reminder.Draft(title: "Go to the gym", category: "Personal", priority: "Low")
Reminder.Draft(title: "Pick up dry cleaning", category: "Personal")
Reminder.Draft(title: "Prepare talk", category: "Work", priority: "High")
Reminder.Draft(title: "Send status report", category: "Work", priority: "Low")
}
.execute(db)
}
try! migrator.migrate(databaseQueue)
return databaseQueue
}
}
#Preview {
let _ = prepareDependencies {
$0.defaultDatabase = .sectionedQueryDatabase
}
NavigationStack {
CaseStudyView {
SectionedQueryDemo()
}
}
}