You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -25,7 +25,7 @@ library, and enforced at compile time, making it painless to adopt best practice
25
25
26
26
```swift
27
27
// Query from the main context
28
-
let people = Query<Person>()
28
+
let people =tryQuery<Person>()
29
29
.include(#Predicate { $0.age>=18 } )
30
30
.sortBy(\.age)
31
31
.results(in: modelContainer)
@@ -53,7 +53,7 @@ Task.detached {
53
53
### Building Queries
54
54
55
55
Queries are an expressive layer on top of SwiftData that allow us to quickly build
56
-
complex fetch decriptors by successively applying refinements. The resulting query can
56
+
complex fetch descriptors by successively applying refinements. The resulting query can
57
57
be saved for reuse or performed immediately.
58
58
59
59
Queries can be initialized explicitly, but `PersistentModel` has also been extended
@@ -161,7 +161,27 @@ been applied to this query, we'll just get the first five results:
161
161
Person[0..<5]
162
162
```
163
163
164
-
### Fetching results
164
+
#### Prefetching relationships
165
+
166
+
When you know you'll need related objects, you can prefetch relationships to reduce trips to the persistent store:
167
+
168
+
```swift
169
+
// Prefetch multiple relationships
170
+
let ordersWithDetails = Order
171
+
.include(#Predicate { $0.status== .active })
172
+
.prefetchRelationships(\.customer, \.items)
173
+
```
174
+
175
+
#### Fetching specific properties
176
+
177
+
To reduce memory usage, you can fetch only specific properties instead of full objects:
178
+
179
+
```swift
180
+
// Fetch only specific properties for better performance
181
+
let lightweightPeople = Person.fetchKeyPaths(\.name, \.age)
182
+
```
183
+
184
+
### Executing queries
165
185
166
186
Queries are just descriptions of how to fetch objects from a context. To make them
167
187
useful, we want to be able to perform them. When fetching results on the main actor,
@@ -174,13 +194,13 @@ Often we just want to fetch a single result.
174
194
```swift
175
195
let jillQuery = Person.include(#Predicate { $0.name=="Jill" })
176
196
177
-
let jill = jillQuery.first(in: modelContainer)
178
-
let lastJill = jillQuery.last(in: modelContainer)
197
+
let jill =tryjillQuery.first(in: modelContainer)
198
+
let lastJill =tryjillQuery.last(in: modelContainer)
179
199
```
180
200
Or any result:
181
201
182
202
```swift
183
-
let anyone = Person.any(in: modelContainer)
203
+
let anyone =tryPerson.any(in: modelContainer)
184
204
```
185
205
186
206
@@ -190,7 +210,7 @@ When we want to fetch all query results in memory, we can use `results`:
190
210
191
211
```swift
192
212
let notJillQuery = Person.exclude(#Predicate { $0.name=="Jill" })
193
-
let notJills = notJillQuery.results(in: modelContainer)
213
+
let notJills =trynotJillQuery.results(in: modelContainer)
194
214
```
195
215
196
216
#### Lazy results
@@ -199,7 +219,7 @@ Sometimes we want a result that is lazily evaluated. For these cases we can get
199
219
`FetchResultsCollection` using `fetchedResults`:
200
220
201
221
```swift
202
-
let lazyAdults = Person
222
+
let lazyAdults =tryPerson
203
223
.include(#Predicate { $0.age>25 })
204
224
.fetchedResults(in: modelContainer)
205
225
```
@@ -211,16 +231,35 @@ based on a set of filters, or create a new one by default in the case that objec
211
231
does not yet exist. This is easy with SwiftQuery using `findOrCreate`:
212
232
213
233
```swift
214
-
let jill = Person
234
+
let jill =tryPerson
215
235
.include(#Predicate { $0.name=="Jill" })
216
236
.findOrCreate(in: container) {
217
237
Person(name: "Jill")
218
238
}
219
239
```
220
240
241
+
#### Deleting objects
242
+
243
+
We can delete just the objects matching a refined query:
244
+
245
+
```swift
246
+
try Person
247
+
.include(#Predicate { $0.name=="Jill" })
248
+
.delete(in: container)
249
+
```
250
+
251
+
Or we can delete every record of a particular type:
252
+
253
+
```swift
254
+
try Query<Person>().delete(in: container)
255
+
try Person.deleteAll(in: container)
256
+
```
257
+
258
+
`PersistentModel.deleteAll` is equivalent to deleting with an empty query.
259
+
221
260
### Async fetches
222
261
223
-
Where SwiftQuery really shines is it's automatic support for performing queries
262
+
Where SwiftQuery really shines is its automatic support for performing queries
224
263
in a concurrency environment. The current isolation context is passed in to each function
225
264
that performs a query, so if you have a custom model actor, you can freely perform
226
265
queries and operate on the results inside the actor:
@@ -275,6 +314,95 @@ effectively makes it impossible to use the models returned from a query incorrec
275
314
a multi-context environment, thus guaranteeing the SwiftData concurrency contract at
276
315
compile time.
277
316
317
+
### Observable Queries
318
+
319
+
Often in the context of view models or views we'd like to passively observe a Query and be notified of changes. SwiftQuery provides property wrappers that automatically update when the underlying data changes. These wrappers use Swift's `@Observable` framework and notify observers whenever the persistent store changes, even if that happens as a result of something like iCloud sync.
320
+
321
+
Observable queries use the main context by default. If you are using them inside a macro like `@Observable`, you must add `@ObservationIgnored`. Listeners will still be notified, but not through the enclosing observable.
322
+
323
+
#### Fetch types
324
+
325
+
326
+
`FetchFirst` fetches and tracks the first result matching a query, if any.
`FetchResults` fetches and tracks results as a lazy `FetchResultsCollection` with configurable batch size. Useful for very large datasets or performance critical screens.
0 commit comments