forked from pointfreeco/sqlite-data
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFetchSubscription.swift
More file actions
46 lines (42 loc) · 1.54 KB
/
FetchSubscription.swift
File metadata and controls
46 lines (42 loc) · 1.54 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
import ConcurrencyExtras
import Sharing
/// A subscription associated with `@FetchAll`, `@FetchOne`, and `@Fetch` observation.
///
/// This value can be useful in associating the lifetime of observing a query to the lifetime of a
/// SwiftUI view _via_ the `task` view modifier. For example, loading a query in a view's `task`
/// will automatically cancel the observation when drilling down into a child view, and restart
/// observation when popping back to the view:
///
/// ```swift
/// .task {
/// try? await $reminders.load(Reminder.all).task
/// }
/// ```
public struct FetchSubscription: Sendable {
let cancellable = LockIsolated<Task<Void, any Error>?>(nil)
let onCancel: @Sendable () -> Void
init<Value>(sharedReader: SharedReader<Value>) {
onCancel = { sharedReader.projectedValue = SharedReader(value: sharedReader.wrappedValue) }
}
/// An async handle to the given fetch observation.
///
/// This handle will suspend until the current task is cancelled, at which point it will terminate
/// the observation of the associated ``FetchAll``, ``FetchOne``, or ``Fetch``.
public var task: Void {
get async throws {
let task = Task {
try await withTaskCancellationHandler {
try await Task.never()
} onCancel: {
onCancel()
}
}
cancellable.withValue { $0 = task }
try await task.cancellableValue
}
}
/// Cancels the database observation of the associated ``FetchAll``, ``FetchOne``, or ``Fetch``.
public func cancel() {
cancellable.value?.cancel()
}
}