Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ jobs:
name: macOS
strategy:
matrix:
xcode: ['16.4']
xcode: ['26.1']
config: ['debug', 'release']
runs-on: macos-15
runs-on: macos-26
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Select Xcode ${{ matrix.xcode }}
run: sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode }}.app
- name: Run ${{ matrix.config }} tests
Expand All @@ -28,13 +28,13 @@ jobs:
name: Examples
strategy:
matrix:
xcode: ['16.4']
xcode: ['26.1']
config: ['debug']
scheme: ['Reminders', 'CaseStudies', 'SyncUps']
runs-on: macos-15
runs-on: macos-26
continue-on-error: true
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Select Xcode ${{ matrix.xcode }}
run: sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode }}.app
- name: List devices available
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Examples/Reminders/ReminderForm.swift
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ struct ReminderFormView: View {
}
.task(id: reminder.remindersListID) {
await withErrorReporting {
try await $remindersList.load(RemindersList.find(reminder.remindersListID))
try await $remindersList.load(RemindersList.find(reminder.remindersListID)).task
}
}
}
Expand Down
10 changes: 8 additions & 2 deletions Examples/Reminders/Schema.swift
Original file line number Diff line number Diff line change
Expand Up @@ -387,8 +387,14 @@ nonisolated private let logger = Logger(subsystem: "Reminders", category: "Datab
func seedSampleData() throws {
@Dependency(\.date.now) var now
@Dependency(\.uuid) var uuid
let remindersListIDs = (0...2).map { _ in uuid() }
let reminderIDs = (0...10).map { _ in uuid() }
var remindersListIDs: [UUID] = []
for _ in 0...2 {
remindersListIDs.append(uuid())
}
var reminderIDs: [UUID] = []
for _ in 0...10 {
reminderIDs.append(uuid())
}
try seed {
RemindersList(
id: remindersListIDs[0],
Expand Down
2 changes: 2 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ let package = Package(
.package(url: "https://github.com/pointfreeco/swift-concurrency-extras", from: "1.0.0"),
.package(url: "https://github.com/pointfreeco/swift-custom-dump", from: "1.3.3"),
.package(url: "https://github.com/pointfreeco/swift-dependencies", from: "1.9.0"),
.package(url: "https://github.com/pointfreeco/swift-perception", from: "2.0.0"),
.package(url: "https://github.com/pointfreeco/swift-sharing", from: "2.3.0"),
.package(url: "https://github.com/pointfreeco/swift-snapshot-testing", from: "1.18.4"),
.package(
Expand All @@ -53,6 +54,7 @@ let package = Package(
.product(name: "GRDB", package: "GRDB.swift"),
.product(name: "IssueReporting", package: "xctest-dynamic-overlay"),
.product(name: "OrderedCollections", package: "swift-collections"),
.product(name: "Perception", package: "swift-perception"),
.product(name: "Sharing", package: "swift-sharing"),
.product(name: "StructuredQueriesSQLite", package: "swift-structured-queries"),
.product(
Expand Down
17 changes: 17 additions & 0 deletions Sources/SQLiteData/Documentation.docc/Articles/MigrationGuides.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Migration guides

Learn how to upgrade your application to the latest version of SQLiteData.

## Overview

SQLiteData is under constant development, and we are always looking for ways to simplify the
library and make it more powerful. As such, we often need to deprecate certain APIs in favor of
newer ones. We recommend people update their code as quickly as possible to the newest APIs, and
these guides contain tips to do so.

> Important: Before following any particular migration guide be sure you have followed all the
> preceding migration guides.

## Topics

- <doc:MigratingTo1.4>
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Migrating to 1.4

SQLiteData 1.4 introduces a new tool for tying the lifecycle database subscriptions to the
lifecycle of the surrounding async context, but it may incidentally cause "Result of call …
is unused" warnings in your project.

## Overview

The `load` method defined on [`@FetchAll`](<doc:FetchAll>) / [`@FetchOne`](<doc:FetchOne>) /
[`@Fetch`](<doc:Fetch>) all now return a discardable result, ``FetchSubscription``. Awaiting the
``FetchSubscription/task`` of that result ties the lifecycle of the subscription to the database
to the lifecycle of the surrounding async context, which can help views to automatically
unsubscribe from the database when they are not visible.

However, when used with `withErrorReporting` you are likely to get the following warning:

```swift
private func updateQuery() async {
// ⚠️ Result of call to 'withErrorReporting(_:to:fileID:filePath:line:column:isolation:catching:)' is unused
await withErrorReporting {
try await $rows.load(…)
}
}
```

This is happening because although `load` has a discardable result, Swift does not propagate that
to `withErrorReporting`, and so Swift thinks you have an unused value. To fix you will need to
explicitly ignore the result with `_ = `:

```swift
private func updateQuery() async {
_ = await withErrorReporting {
try await $rows.load(…)
}
}
```
1 change: 1 addition & 0 deletions Sources/SQLiteData/Documentation.docc/SQLiteData.md
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ with SQLite to take full advantage of GRDB and SQLiteData.
- ``FetchAll``
- ``FetchOne``
- ``Fetch``
- ``FetchSubscription``

### CloudKit synchronization and sharing

Expand Down
15 changes: 12 additions & 3 deletions Sources/SQLiteData/Fetch.swift
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,14 @@ public struct Fetch<Value: Sendable>: Sendable {
/// - request: A request describing the data to fetch.
/// - database: The database to read from. A value of `nil` will use the default database
/// (`@Dependency(\.defaultDatabase)`).
/// - Returns: A subscription associated with the observation.
@discardableResult
public func load(
_ request: some FetchKeyRequest<Value>,
database: (any DatabaseReader)? = nil
) async throws {
) async throws -> FetchSubscription {
try await sharedReader.load(.fetch(request, database: database))
return FetchSubscription(sharedReader: sharedReader)
}
}

Expand Down Expand Up @@ -136,12 +139,15 @@ extension Fetch {
/// (`@Dependency(\.defaultDatabase)`).
/// - scheduler: The scheduler to observe from. By default, database observation is performed
/// asynchronously on the main queue.
/// - Returns: A subscription associated with the observation.
@discardableResult
public func load(
_ request: some FetchKeyRequest<Value>,
database: (any DatabaseReader)? = nil,
scheduler: some ValueObservationScheduler & Hashable
) async throws {
) async throws -> FetchSubscription {
try await sharedReader.load(.fetch(request, database: database, scheduler: scheduler))
return FetchSubscription(sharedReader: sharedReader)
}
}

Expand Down Expand Up @@ -193,13 +199,16 @@ extension Fetch: Equatable where Value: Equatable {
/// (`@Dependency(\.defaultDatabase)`).
/// - animation: The animation to use for user interface changes that result from changes to
/// the fetched results.
/// - Returns: A subscription associated with the observation.
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
@discardableResult
public func load(
_ request: some FetchKeyRequest<Value>,
database: (any DatabaseReader)? = nil,
animation: Animation
) async throws {
) async throws -> FetchSubscription {
try await sharedReader.load(.fetch(request, database: database, animation: animation))
return FetchSubscription(sharedReader: sharedReader)
}
}
#endif
Loading