diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 2f399dee..25fda7cf 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -27,7 +27,7 @@ body:
required: false
- label: If possible, I've reproduced the issue using the `main` branch of this package.
required: false
- - label: This issue hasn't been addressed in an [existing GitHub issue](https://github.com/pointfreeco/sharing-grdb/issues) or [discussion](https://github.com/pointfreeco/sharing-grdb/discussions).
+ - label: This issue hasn't been addressed in an [existing GitHub issue](https://github.com/pointfreeco/sqlite-data/issues) or [discussion](https://github.com/pointfreeco/sqlite-data/discussions).
required: true
- type: textarea
attributes:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 45dce330..030e709c 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -17,14 +17,14 @@ jobs:
env:
INCOMING_WEBHOOK_URL: ${{ secrets.SLACK_PROJECT_CHANNEL_WEBHOOK_URL }}
with:
- text: sharing-grdb ${{ github.event.release.tag_name }} has been released.
+ text: sqlite-data ${{ github.event.release.tag_name }} has been released.
blocks: |
[
{
"type": "header",
"text": {
"type": "plain_text",
- "text": "sharing-grdb ${{ github.event.release.tag_name}}"
+ "text": "sqlite-data ${{ github.event.release.tag_name}}"
}
},
{
@@ -56,14 +56,14 @@ jobs:
env:
INCOMING_WEBHOOK_URL: ${{ secrets.SLACK_RELEASES_WEBHOOK_URL }}
with:
- text: sharing-grdb ${{ github.event.release.tag_name }} has been released.
+ text: sqlite-data ${{ github.event.release.tag_name }} has been released.
blocks: |
[
{
"type": "header",
"text": {
"type": "plain_text",
- "text": "sharing-grdb ${{ github.event.release.tag_name}}"
+ "text": "sqlite-data ${{ github.event.release.tag_name}}"
}
},
{
diff --git a/Examples/CloudKitDemo/Assets.xcassets/AppIcon.appiconset/Contents.json b/Examples/CloudKitDemo/Assets.xcassets/AppIcon.appiconset/Contents.json
index ffdfe150..23058801 100644
--- a/Examples/CloudKitDemo/Assets.xcassets/AppIcon.appiconset/Contents.json
+++ b/Examples/CloudKitDemo/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -26,56 +26,6 @@
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
- },
- {
- "idiom" : "mac",
- "scale" : "1x",
- "size" : "16x16"
- },
- {
- "idiom" : "mac",
- "scale" : "2x",
- "size" : "16x16"
- },
- {
- "idiom" : "mac",
- "scale" : "1x",
- "size" : "32x32"
- },
- {
- "idiom" : "mac",
- "scale" : "2x",
- "size" : "32x32"
- },
- {
- "idiom" : "mac",
- "scale" : "1x",
- "size" : "128x128"
- },
- {
- "idiom" : "mac",
- "scale" : "2x",
- "size" : "128x128"
- },
- {
- "idiom" : "mac",
- "scale" : "1x",
- "size" : "256x256"
- },
- {
- "idiom" : "mac",
- "scale" : "2x",
- "size" : "256x256"
- },
- {
- "idiom" : "mac",
- "scale" : "1x",
- "size" : "512x512"
- },
- {
- "idiom" : "mac",
- "scale" : "2x",
- "size" : "512x512"
}
],
"info" : {
diff --git a/Examples/CloudKitDemo/CloudKitDemo.entitlements b/Examples/CloudKitDemo/CloudKitDemo.entitlements
index 5df5b1b1..d013bfc9 100644
--- a/Examples/CloudKitDemo/CloudKitDemo.entitlements
+++ b/Examples/CloudKitDemo/CloudKitDemo.entitlements
@@ -4,19 +4,13 @@
aps-environment
development
- com.apple.developer.aps-environment
- development
com.apple.developer.icloud-container-identifiers
- iCloud.co.pointfree.SQLiteData.demos.CloudKitDemo
+ iCloud.co.pointfree.SQLiteData.CloudKitDemo
com.apple.developer.icloud-services
CloudKit
- com.apple.security.app-sandbox
-
- com.apple.security.files.user-selected.read-only
-
diff --git a/Examples/CloudKitDemo/CloudKitDemoApp.swift b/Examples/CloudKitDemo/CloudKitDemoApp.swift
index 40b628ce..aef2e449 100644
--- a/Examples/CloudKitDemo/CloudKitDemoApp.swift
+++ b/Examples/CloudKitDemo/CloudKitDemoApp.swift
@@ -2,15 +2,16 @@ import CloudKit
import SQLiteData
import SwiftUI
-#if canImport
- import UIKit
-#endif
-
@main
struct CloudKitDemoApp: App {
- #if canImport(UIKit)
- @UIApplicationDelegateAdaptor private var appDelegate: AppDelegate
- #endif
+ @UIApplicationDelegateAdaptor private var appDelegate: AppDelegate
+
+ init() {
+ try! prepareDependencies {
+ try $0.bootstrapDatabase()
+ }
+ }
+
var body: some Scene {
WindowGroup {
NavigationStack {
@@ -20,62 +21,43 @@ struct CloudKitDemoApp: App {
}
}
-#if canImport(UIKit)
- class AppDelegate: UIResponder, UIApplicationDelegate, ObservableObject {
- func application(
- _ application: UIApplication,
- didFinishLaunchingWithOptions launchOptions: [UIApplication
- .LaunchOptionsKey: Any]? = nil
- ) -> Bool {
- try! prepareDependencies {
- $0.defaultDatabase = try appDatabase()
- $0.defaultSyncEngine = try SyncEngine(
- for: $0.defaultDatabase,
- tables: Counter.self
- )
- }
- return true
- }
-
- func application(
- _ application: UIApplication,
- configurationForConnecting connectingSceneSession: UISceneSession,
- options: UIScene.ConnectionOptions
- ) -> UISceneConfiguration {
- let configuration = UISceneConfiguration(
- name: "Default Configuration",
- sessionRole: connectingSceneSession.role
- )
- configuration.delegateClass = SceneDelegate.self
- return configuration
- }
+class AppDelegate: UIResponder, UIApplicationDelegate, ObservableObject {
+ func application(
+ _ application: UIApplication,
+ configurationForConnecting connectingSceneSession: UISceneSession,
+ options: UIScene.ConnectionOptions
+ ) -> UISceneConfiguration {
+ let configuration = UISceneConfiguration(
+ name: "Default Configuration",
+ sessionRole: connectingSceneSession.role
+ )
+ configuration.delegateClass = SceneDelegate.self
+ return configuration
}
+}
- class SceneDelegate: UIResponder, UIWindowSceneDelegate {
- @Dependency(\.defaultSyncEngine) var syncEngine
- var window: UIWindow?
+class SceneDelegate: UIResponder, UIWindowSceneDelegate {
+ @Dependency(\.defaultSyncEngine) var syncEngine
+ var window: UIWindow?
- func windowScene(
- _ windowScene: UIWindowScene,
- userDidAcceptCloudKitShareWith cloudKitShareMetadata: CKShare.Metadata
- ) {
- Task {
- try await syncEngine.acceptShare(metadata: cloudKitShareMetadata)
- }
+ func windowScene(
+ _ windowScene: UIWindowScene,
+ userDidAcceptCloudKitShareWith cloudKitShareMetadata: CKShare.Metadata
+ ) {
+ Task {
+ try await syncEngine.acceptShare(metadata: cloudKitShareMetadata)
}
+ }
- func scene(
- _ scene: UIScene,
- willConnectTo session: UISceneSession,
- options connectionOptions: UIScene.ConnectionOptions
- ) {
- guard let cloudKitShareMetadata = connectionOptions.cloudKitShareMetadata
- else {
- return
- }
- Task {
- try await syncEngine.acceptShare(metadata: cloudKitShareMetadata)
- }
+ func scene(
+ _ scene: UIScene,
+ willConnectTo session: UISceneSession,
+ options connectionOptions: UIScene.ConnectionOptions
+ ) {
+ guard let cloudKitShareMetadata = connectionOptions.cloudKitShareMetadata
+ else { return }
+ Task {
+ try await syncEngine.acceptShare(metadata: cloudKitShareMetadata)
}
}
-#endif
+}
diff --git a/Examples/CloudKitDemo/CountersListFeature.swift b/Examples/CloudKitDemo/CountersListFeature.swift
index a356784d..98b904e2 100644
--- a/Examples/CloudKitDemo/CountersListFeature.swift
+++ b/Examples/CloudKitDemo/CountersListFeature.swift
@@ -16,14 +16,7 @@ struct CountersListView: View {
.buttonStyle(.borderless)
}
.onDelete { indexSet in
- withErrorReporting {
- try database.write { db in
- for index in indexSet {
- try Counter.find(counters[index].id).delete()
- .execute(db)
- }
- }
- }
+ deleteRows(at: indexSet)
}
}
}
@@ -42,6 +35,17 @@ struct CountersListView: View {
}
}
}
+
+ func deleteRows(at indexSet: IndexSet) {
+ withErrorReporting {
+ try database.write { db in
+ for index in indexSet {
+ try Counter.find(counters[index].id).delete()
+ .execute(db)
+ }
+ }
+ }
+ }
}
struct CounterRow: View {
@@ -55,32 +59,14 @@ struct CounterRow: View {
HStack {
Text("\(counter.count)")
Button("-") {
- withErrorReporting {
- try database.write { db in
- try Counter.find(counter.id).update {
- $0.count -= 1
- }
- .execute(db)
- }
- }
+ decrementButtonTapped()
}
Button("+") {
- withErrorReporting {
- try database.write { db in
- try Counter.find(counter.id).update {
- $0.count += 1
- }
- .execute(db)
- }
- }
+ incrementButtonTapped()
}
Spacer()
Button {
- Task {
- sharedRecord = try await syncEngine.share(record: counter) { share in
- share[CKShare.SystemFieldKey.title] = "Join my counter!"
- }
- }
+ shareButtonTapped()
} label: {
Image(systemName: "square.and.arrow.up")
}
@@ -90,4 +76,34 @@ struct CounterRow: View {
CloudSharingView(sharedRecord: sharedRecord)
}
}
+
+ func shareButtonTapped() {
+ Task {
+ sharedRecord = try await syncEngine.share(record: counter) { share in
+ share[CKShare.SystemFieldKey.title] = "Join my counter!"
+ }
+ }
+ }
+
+ func decrementButtonTapped() {
+ withErrorReporting {
+ try database.write { db in
+ try Counter.find(counter.id).update {
+ $0.count -= 1
+ }
+ .execute(db)
+ }
+ }
+ }
+
+ func incrementButtonTapped() {
+ withErrorReporting {
+ try database.write { db in
+ try Counter.find(counter.id).update {
+ $0.count += 1
+ }
+ .execute(db)
+ }
+ }
+ }
}
diff --git a/Examples/CloudKitDemo/Info.plist b/Examples/CloudKitDemo/Info.plist
index 16fd2333..ca9a074a 100644
--- a/Examples/CloudKitDemo/Info.plist
+++ b/Examples/CloudKitDemo/Info.plist
@@ -2,15 +2,6 @@
- CKSharingSupported
-
- UIApplicationSceneManifest
-
- UIApplicationSupportsMultipleScenes
-
- UISceneConfigurations
-
-
UIBackgroundModes
remote-notification
diff --git a/Examples/CloudKitDemo/Schema.swift b/Examples/CloudKitDemo/Schema.swift
index ca892d0d..f3e5fa87 100644
--- a/Examples/CloudKitDemo/Schema.swift
+++ b/Examples/CloudKitDemo/Schema.swift
@@ -8,57 +8,52 @@ struct Counter: Identifiable {
var count = 0
}
-func appDatabase() throws -> any DatabaseWriter {
- @Dependency(\.context) var context
- let database: any DatabaseWriter
- var configuration = Configuration()
- configuration.prepareDatabase { db in
- try db.attachMetadatabase(
- containerIdentifier: "iCloud.co.pointfree.SQLiteData.demos.CloudKitDemo")
- #if DEBUG
- db.trace(options: .profile) {
- if context == .live {
- logger.debug("\($0.expandedDescription)")
- } else {
- print("\($0.expandedDescription)")
+extension DependencyValues {
+ mutating func bootstrapDatabase() throws {
+ @Dependency(\.context) var context
+ var configuration = Configuration()
+ configuration.prepareDatabase { db in
+ try db.attachMetadatabase()
+ #if DEBUG
+ db.trace(options: .profile) {
+ if context == .live {
+ logger.debug("\($0.expandedDescription)")
+ } else {
+ print("\($0.expandedDescription)")
+ }
}
- }
- #endif
- }
- if context == .preview {
- database = try DatabaseQueue(configuration: configuration)
- } else {
- let path =
- context == .live
- ? URL.documentsDirectory.appending(component: "db.sqlite").path()
- : URL.temporaryDirectory.appending(component: "\(UUID().uuidString)-db.sqlite").path()
+ #endif
+ }
+ let database = try SQLiteData.defaultDatabase(configuration: configuration)
logger.debug(
"""
App database
- open "\(path)"
+ open "\(database.path)"
"""
)
- database = try DatabasePool(path: path, configuration: configuration)
- }
- var migrator = DatabaseMigrator()
- #if DEBUG
- migrator.eraseDatabaseOnSchemaChange = true
- #endif
- migrator.registerMigration("Create tables") { db in
- try #sql(
- """
- CREATE TABLE "counters" (
- "id" TEXT PRIMARY KEY NOT NULL ON CONFLICT REPLACE DEFAULT (uuid()),
- "count" INT NOT NULL DEFAULT 0
+ var migrator = DatabaseMigrator()
+ #if DEBUG
+ migrator.eraseDatabaseOnSchemaChange = true
+ #endif
+ migrator.registerMigration("Create tables") { db in
+ try #sql(
+ """
+ CREATE TABLE "counters" (
+ "id" TEXT PRIMARY KEY NOT NULL ON CONFLICT REPLACE DEFAULT (uuid()),
+ "count" INT NOT NULL ON CONFLICT REPLACE DEFAULT 0
+ )
+ """
)
- """
+ .execute(db)
+ }
+ try migrator.migrate(database)
+ defaultDatabase = database
+ defaultSyncEngine = try SyncEngine(
+ for: defaultDatabase,
+ tables: Counter.self
)
- .execute(db)
}
- try migrator.migrate(database)
-
- return database
}
private let logger = Logger(subsystem: "CloudKitDemo", category: "Database")
diff --git a/Examples/CloudKitDemoTests/CloudKitDemoTests.swift b/Examples/CloudKitDemoTests/CloudKitDemoTests.swift
deleted file mode 100644
index 76468d0e..00000000
--- a/Examples/CloudKitDemoTests/CloudKitDemoTests.swift
+++ /dev/null
@@ -1,16 +0,0 @@
-//
-// CloudKitDemoTests.swift
-// CloudKitDemoTests
-//
-// Created by Brandon Williams on 6/6/25.
-//
-
-import Testing
-
-struct CloudKitDemoTests {
-
- @Test func example() async throws {
- // Write your test here and use APIs like `#expect(...)` to check expected conditions.
- }
-
-}
diff --git a/Examples/CloudKitPlayground/Assets.xcassets/AccentColor.colorset/Contents.json b/Examples/CloudKitPlayground/Assets.xcassets/AccentColor.colorset/Contents.json
deleted file mode 100644
index eb878970..00000000
--- a/Examples/CloudKitPlayground/Assets.xcassets/AccentColor.colorset/Contents.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "colors" : [
- {
- "idiom" : "universal"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Examples/CloudKitPlayground/Assets.xcassets/AppIcon.appiconset/Contents.json b/Examples/CloudKitPlayground/Assets.xcassets/AppIcon.appiconset/Contents.json
deleted file mode 100644
index 23058801..00000000
--- a/Examples/CloudKitPlayground/Assets.xcassets/AppIcon.appiconset/Contents.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "universal",
- "platform" : "ios",
- "size" : "1024x1024"
- },
- {
- "appearances" : [
- {
- "appearance" : "luminosity",
- "value" : "dark"
- }
- ],
- "idiom" : "universal",
- "platform" : "ios",
- "size" : "1024x1024"
- },
- {
- "appearances" : [
- {
- "appearance" : "luminosity",
- "value" : "tinted"
- }
- ],
- "idiom" : "universal",
- "platform" : "ios",
- "size" : "1024x1024"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Examples/CloudKitPlayground/Assets.xcassets/Contents.json b/Examples/CloudKitPlayground/Assets.xcassets/Contents.json
deleted file mode 100644
index 73c00596..00000000
--- a/Examples/CloudKitPlayground/Assets.xcassets/Contents.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Examples/CloudKitPlayground/CloudKitPlayground.entitlements b/Examples/CloudKitPlayground/CloudKitPlayground.entitlements
deleted file mode 100644
index 97100297..00000000
--- a/Examples/CloudKitPlayground/CloudKitPlayground.entitlements
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
- aps-environment
- development
- com.apple.developer.icloud-container-identifiers
-
- iCloud.co.pointfree.SQLiteData.demos.CloudKitPlayground
-
- com.apple.developer.icloud-services
-
- CloudKit
-
-
-
diff --git a/Examples/CloudKitPlayground/CloudKitPlaygroundApp.swift b/Examples/CloudKitPlayground/CloudKitPlaygroundApp.swift
deleted file mode 100644
index c4ee8a3b..00000000
--- a/Examples/CloudKitPlayground/CloudKitPlaygroundApp.swift
+++ /dev/null
@@ -1,78 +0,0 @@
-import CloudKit
-import SQLiteData
-import SwiftUI
-import UIKit
-
-@main
-struct CloudKitPlaygroundApp: App {
- @UIApplicationDelegateAdaptor var delegate: AppDelegate
-
- init() {
- prepareDependencies {
- $0.defaultDatabase = try! appDatabase()
- $0.defaultSyncEngine = try! SyncEngine(
- for: $0.defaultDatabase,
- tables: ModelA.self,
- ModelB.self,
- ModelC.self
- )
- }
- }
- var body: some Scene {
- WindowGroup {
- NavigationStack {
- ModelAView()
- }
- }
- }
-}
-
-class AppDelegate: UIResponder, UIApplicationDelegate {
- func application(
- _ application: UIApplication,
- didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
- ) -> Bool {
- return true
- }
-
- func application(
- _ application: UIApplication,
- configurationForConnecting connectingSceneSession: UISceneSession,
- options: UIScene.ConnectionOptions
- ) -> UISceneConfiguration {
- let configuration = UISceneConfiguration(
- name: "Default Configuration",
- sessionRole: connectingSceneSession.role
- )
- configuration.delegateClass = SceneDelegate.self
- return configuration
- }
-}
-
-class SceneDelegate: UIResponder, UIWindowSceneDelegate {
- @Dependency(\.defaultSyncEngine) var syncEngine
- var window: UIWindow?
-
- func windowScene(
- _ windowScene: UIWindowScene,
- userDidAcceptCloudKitShareWith cloudKitShareMetadata: CKShare.Metadata
- ) {
- Task {
- try await syncEngine.acceptShare(metadata: cloudKitShareMetadata)
- }
- }
-
- func scene(
- _ scene: UIScene,
- willConnectTo session: UISceneSession,
- options connectionOptions: UIScene.ConnectionOptions
- ) {
- guard let cloudKitShareMetadata = connectionOptions.cloudKitShareMetadata
- else {
- return
- }
- Task {
- try await syncEngine.acceptShare(metadata: cloudKitShareMetadata)
- }
- }
-}
diff --git a/Examples/CloudKitPlayground/ContentView.swift b/Examples/CloudKitPlayground/ContentView.swift
deleted file mode 100644
index 4503945e..00000000
--- a/Examples/CloudKitPlayground/ContentView.swift
+++ /dev/null
@@ -1,24 +0,0 @@
-//
-// ContentView.swift
-// CloudKitPlayground
-//
-// Created by Brandon Williams on 7/9/25.
-//
-
-import SwiftUI
-
-struct ContentView: View {
- var body: some View {
- VStack {
- Image(systemName: "globe")
- .imageScale(.large)
- .foregroundStyle(.tint)
- Text("Hello, world!")
- }
- .padding()
- }
-}
-
-#Preview {
- ContentView()
-}
diff --git a/Examples/CloudKitPlayground/Info.plist b/Examples/CloudKitPlayground/Info.plist
deleted file mode 100644
index 9ef96ef8..00000000
--- a/Examples/CloudKitPlayground/Info.plist
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
- CKSharingSupported
-
- UIBackgroundModes
-
- remote-notification
-
-
-
diff --git a/Examples/CloudKitPlayground/ModelAView.swift b/Examples/CloudKitPlayground/ModelAView.swift
deleted file mode 100644
index 3835281d..00000000
--- a/Examples/CloudKitPlayground/ModelAView.swift
+++ /dev/null
@@ -1,71 +0,0 @@
-import CloudKit
-import SQLiteData
-import SwiftUI
-
-struct ModelAView: View {
- @FetchAll var models: [ModelA]
- @Dependency(\.defaultDatabase) var database
- @Dependency(\.defaultSyncEngine) var syncEngine
-
- @State var sharedRecord: SharedRecord?
-
- var body: some View {
- List {
- ForEach(models) { model in
- HStack {
- Button("-") {
- withErrorReporting {
- try database.write { db in
- try ModelA.find(model.id).update { $0.count -= 1 }.execute(db)
- }
- }
- }
- Text("\(model.count)")
- Button("+") {
- withErrorReporting {
- try database.write { db in
- try ModelA.find(model.id).update { $0.count += 1 }.execute(db)
- }
- }
- }
- Spacer()
- NavigationLink("Go") {
- ModelBView(modelA: model)
- }
- Spacer()
- Button {
- Task {
- sharedRecord = try await syncEngine.share(record: model) { share in
- share[CKShare.SystemFieldKey.title] = "Join my ModelA(\(model.count))"
- }
- }
- } label: {
- Image(systemName: "square.and.arrow.up")
- }
- }
- .buttonStyle(.plain)
- }
- .onDelete { indexSet in
- for index in indexSet {
- withErrorReporting {
- try database.write { db in
- try ModelA.find(models[index].id).delete().execute(db)
- }
- }
- }
- }
- }
- .sheet(item: $sharedRecord) { sharedRecord in
- CloudSharingView(sharedRecord: sharedRecord)
- }
- .toolbar {
- Button("Add") {
- withErrorReporting {
- try database.write { db in
- try ModelA.insert { ModelA.Draft() }.execute(db)
- }
- }
- }
- }
- }
-}
diff --git a/Examples/CloudKitPlayground/ModelBView.swift b/Examples/CloudKitPlayground/ModelBView.swift
deleted file mode 100644
index 0587fbd8..00000000
--- a/Examples/CloudKitPlayground/ModelBView.swift
+++ /dev/null
@@ -1,73 +0,0 @@
-import SQLiteData
-import SwiftUI
-
-struct ModelBView: View {
- let modelA: ModelA
- @FetchAll var models: [ModelB]
- @Dependency(\.defaultDatabase) var database
-
- init(modelA: ModelA) {
- self.modelA = modelA
- _models = FetchAll(ModelB.where { $0.modelAID.eq(modelA.id) })
- }
-
- var body: some View {
- List {
- ForEach(models) { model in
- HStack {
- Toggle(
- "On? \(model.isOn ? "YES" : "NO")",
- isOn: Binding {
- model.isOn
- } set: { newValue in
- withErrorReporting {
- try database.write { db in
- try ModelB.find(model.id).update { $0.isOn = newValue }.execute(db)
- }
- }
- })
-
- Spacer()
- NavigationLink("Go") {
- ModelCView(modelB: model)
- }
- }
- .buttonStyle(.plain)
- }
- .onDelete { indexSet in
- for index in indexSet {
- withErrorReporting {
- try database.write { db in
- try ModelB.find(models[index].id).delete().execute(db)
- }
- }
- }
- }
- }
- .toolbar {
- Button("Add") {
- withErrorReporting {
- try database.write { db in
- try ModelB.insert { ModelB.Draft(modelAID: modelA.id) }.execute(db)
- }
- }
- }
- Button("Special") {
- withErrorReporting {
- try database.write { db in
- let modelB = try ModelB.insert { ModelB.Draft(modelAID: modelA.id) }.returning(\.self)
- .fetchOne(db)
- guard let modelB
- else { return }
-
- for index in 1...5 {
- try ModelC
- .insert { ModelC.Draft.init(title: index.description, modelBID: modelB.id) }
- .execute(db)
- }
- }
- }
- }
- }
- }
-}
diff --git a/Examples/CloudKitPlayground/ModelCView.swift b/Examples/CloudKitPlayground/ModelCView.swift
deleted file mode 100644
index 51b9546c..00000000
--- a/Examples/CloudKitPlayground/ModelCView.swift
+++ /dev/null
@@ -1,52 +0,0 @@
-import SQLiteData
-import SwiftUI
-
-struct ModelCView: View {
- let modelB: ModelB
- @FetchAll var models: [ModelC]
- @Dependency(\.defaultDatabase) var database
-
- init(modelB: ModelB) {
- self.modelB = modelB
- _models = FetchAll(ModelC.where { $0.modelBID.eq(modelB.id) })
- }
-
- var body: some View {
- List {
- ForEach(models) { model in
- HStack {
- TextField(
- "Title",
- text: Binding {
- model.title
- } set: { newValue in
- withErrorReporting {
- try database.write { db in
- try ModelC.find(model.id).update { $0.title = newValue }.execute(db)
- }
- }
- })
- }
- .buttonStyle(.plain)
- }
- .onDelete { indexSet in
- for index in indexSet {
- withErrorReporting {
- try database.write { db in
- try ModelC.find(models[index].id).delete().execute(db)
- }
- }
- }
- }
- }
- .toolbar {
- Button("Add") {
- withErrorReporting {
- try database.write { db in
- try ModelC.insert { ModelC.Draft(modelBID: modelB.id) }.execute(db)
- }
- }
- }
- }
- }
-}
diff --git a/Examples/CloudKitPlayground/Schema.swift b/Examples/CloudKitPlayground/Schema.swift
deleted file mode 100644
index 57489dfc..00000000
--- a/Examples/CloudKitPlayground/Schema.swift
+++ /dev/null
@@ -1,88 +0,0 @@
-import Foundation
-import SQLiteData
-import os
-
-@Table struct ModelA: Identifiable {
- let id: UUID
- var count = 0
-}
-@Table struct ModelB: Identifiable {
- let id: UUID
- var isOn = false
- var modelAID: ModelA.ID
-}
-@Table struct ModelC: Identifiable {
- let id: UUID
- var title = ""
- var modelBID: ModelB.ID
-}
-
-func appDatabase() throws -> any DatabaseWriter {
- @Dependency(\.context) var context
- let database: any DatabaseWriter
- var configuration = Configuration()
- configuration.prepareDatabase { db in
- try db.attachMetadatabase()
- #if DEBUG
- db.trace(options: .profile) {
- if context == .live {
- logger.debug("\($0.expandedDescription)")
- } else {
- print("\($0.expandedDescription)")
- }
- }
- #endif
- }
- if context == .preview {
- database = try DatabaseQueue(configuration: configuration)
- } else {
- let path =
- context == .live
- ? URL.documentsDirectory.appending(component: "db.sqlite").path()
- : URL.temporaryDirectory.appending(component: "\(UUID().uuidString)-db.sqlite").path()
- logger.debug(
- """
- App database
- open "\(path)"
- """
- )
- database = try DatabasePool(path: path, configuration: configuration)
- }
- var migrator = DatabaseMigrator()
- migrator.registerMigration("Create tables") { db in
- try #sql(
- """
- CREATE TABLE "modelAs" (
- "id" TEXT PRIMARY KEY NOT NULL ON CONFLICT REPLACE DEFAULT (uuid()),
- "count" INTEGER NOT NULL
- )
- """
- )
- .execute(db)
- try #sql(
- """
- CREATE TABLE "modelBs" (
- "id" TEXT PRIMARY KEY NOT NULL ON CONFLICT REPLACE DEFAULT (uuid()),
- "isOn" INTEGER NOT NULL,
- "modelAID" INTEGER NOT NULL REFERENCES "modelAs"("id") ON DELETE CASCADE
- )
- """
- )
- .execute(db)
- try #sql(
- """
- CREATE TABLE "modelCs" (
- "id" TEXT PRIMARY KEY NOT NULL ON CONFLICT REPLACE DEFAULT (uuid()),
- "title" TEXT NOT NULL,
- "modelBID" INTEGER NOT NULL REFERENCES "modelBs"("id") ON DELETE CASCADE
- )
- """
- )
- .execute(db)
- }
- try migrator.migrate(database)
-
- return database
-}
-
-let logger = Logger(subsystem: "CloudKitPlayground", category: "Database")
diff --git a/Examples/Examples.xcodeproj/project.pbxproj b/Examples/Examples.xcodeproj/project.pbxproj
index a7d7bc4c..893f15a6 100644
--- a/Examples/Examples.xcodeproj/project.pbxproj
+++ b/Examples/Examples.xcodeproj/project.pbxproj
@@ -9,15 +9,16 @@
/* Begin PBXBuildFile section */
CA14DBC92DA884C400E36852 /* CasePaths in Frameworks */ = {isa = PBXBuildFile; productRef = CA14DBC82DA884C400E36852 /* CasePaths */; };
CA2908C92D4AF70E003F165F /* UIKitNavigation in Frameworks */ = {isa = PBXBuildFile; productRef = CA2908C82D4AF70E003F165F /* UIKitNavigation */; };
+ CA2BDE2A2E71C469000974D3 /* SQLiteData in Frameworks */ = {isa = PBXBuildFile; productRef = CA2BDE292E71C469000974D3 /* SQLiteData */; };
+ CA2BDE2C2E71C472000974D3 /* SQLiteData in Frameworks */ = {isa = PBXBuildFile; productRef = CA2BDE2B2E71C472000974D3 /* SQLiteData */; };
+ CA2BDE2E2E71C479000974D3 /* SQLiteData in Frameworks */ = {isa = PBXBuildFile; productRef = CA2BDE2D2E71C479000974D3 /* SQLiteData */; };
+ CA2BDE302E71C480000974D3 /* SQLiteData in Frameworks */ = {isa = PBXBuildFile; productRef = CA2BDE2F2E71C480000974D3 /* SQLiteData */; };
CA5E46912DEBB8570069E0F8 /* SwiftUINavigation in Frameworks */ = {isa = PBXBuildFile; productRef = CA5E46902DEBB8570069E0F8 /* SwiftUINavigation */; };
CA5E47072DECEF0F0069E0F8 /* InlineSnapshotTesting in Frameworks */ = {isa = PBXBuildFile; productRef = CA5E47062DECEF0F0069E0F8 /* InlineSnapshotTesting */; };
CA5E47092DECEFC80069E0F8 /* SnapshotTestingCustomDump in Frameworks */ = {isa = PBXBuildFile; productRef = CA5E47082DECEFC80069E0F8 /* SnapshotTestingCustomDump */; };
CA5E470B2DECF0280069E0F8 /* DependenciesTestSupport in Frameworks */ = {isa = PBXBuildFile; productRef = CA5E470A2DECF0280069E0F8 /* DependenciesTestSupport */; };
- CA6A1D242E68A0A600604D6A /* SQLiteData in Frameworks */ = {isa = PBXBuildFile; productRef = CA6A1D232E68A0A600604D6A /* SQLiteData */; };
CAD001872D874F1F00FA977A /* DependenciesTestSupport in Frameworks */ = {isa = PBXBuildFile; productRef = CAD001862D874F1F00FA977A /* DependenciesTestSupport */; };
DC5FA7482D4C63D60082743E /* DependenciesMacros in Frameworks */ = {isa = PBXBuildFile; productRef = DC5FA7472D4C63D60082743E /* DependenciesMacros */; };
- DC9A3DDE2E6A280700DE41FB /* SQLiteData in Frameworks */ = {isa = PBXBuildFile; productRef = DC9A3DDD2E6A280700DE41FB /* SQLiteData */; };
- DC9A3DE02E6A280F00DE41FB /* SQLiteData in Frameworks */ = {isa = PBXBuildFile; productRef = DC9A3DDF2E6A280F00DE41FB /* SQLiteData */; };
DCBE8A142D4842BF0071F499 /* CasePaths in Frameworks */ = {isa = PBXBuildFile; productRef = DCBE8A132D4842BF0071F499 /* CasePaths */; };
DCF267392D48437300B680BE /* SwiftUINavigation in Frameworks */ = {isa = PBXBuildFile; productRef = DCF267382D48437300B680BE /* SwiftUINavigation */; };
/* End PBXBuildFile section */
@@ -47,6 +48,8 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
+ CA2BDD9D2E71C30B000974D3 /* CloudKitDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CloudKitDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ CA2BDE272E71C42B000974D3 /* sqlite-data */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = "sqlite-data"; path = "/Users/brandon/projects/sqlite-data"; sourceTree = ""; };
CA5E46962DEBFE410069E0F8 /* RemindersTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RemindersTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
CA5F37542D5AFBBC002E1A9E /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; };
CAD0017D2D874E6F00FA977A /* SyncUpTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SyncUpTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -57,6 +60,13 @@
/* End PBXFileReference section */
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
+ CA2BDE332E71C578000974D3 /* Exceptions for "CloudKitDemo" folder in "CloudKitDemo" target */ = {
+ isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
+ membershipExceptions = (
+ Info.plist,
+ );
+ target = CA2BDD9C2E71C30B000974D3 /* CloudKitDemo */;
+ };
CAD4819A2D584B510004799A /* Exceptions for "CaseStudies" folder in "CaseStudies" target */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
@@ -83,6 +93,14 @@
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
/* Begin PBXFileSystemSynchronizedRootGroup section */
+ CA2BDD9E2E71C30B000974D3 /* CloudKitDemo */ = {
+ isa = PBXFileSystemSynchronizedRootGroup;
+ exceptions = (
+ CA2BDE332E71C578000974D3 /* Exceptions for "CloudKitDemo" folder in "CloudKitDemo" target */,
+ );
+ path = CloudKitDemo;
+ sourceTree = "";
+ };
CA5E46972DEBFE410069E0F8 /* RemindersTests */ = {
isa = PBXFileSystemSynchronizedRootGroup;
path = RemindersTests;
@@ -125,6 +143,14 @@
/* End PBXFileSystemSynchronizedRootGroup section */
/* Begin PBXFrameworksBuildPhase section */
+ CA2BDD9A2E71C30B000974D3 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ CA2BDE2A2E71C469000974D3 /* SQLiteData in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
CA5E46932DEBFE410069E0F8 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -147,7 +173,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- DC9A3DDE2E6A280700DE41FB /* SQLiteData in Frameworks */,
+ CA2BDE302E71C480000974D3 /* SQLiteData in Frameworks */,
CA2908C92D4AF70E003F165F /* UIKitNavigation in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -163,7 +189,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- CA6A1D242E68A0A600604D6A /* SQLiteData in Frameworks */,
+ CA2BDE2E2E71C479000974D3 /* SQLiteData in Frameworks */,
CA14DBC92DA884C400E36852 /* CasePaths in Frameworks */,
CA5E46912DEBB8570069E0F8 /* SwiftUINavigation in Frameworks */,
);
@@ -175,7 +201,7 @@
files = (
DCF267392D48437300B680BE /* SwiftUINavigation in Frameworks */,
DC5FA7482D4C63D60082743E /* DependenciesMacros in Frameworks */,
- DC9A3DE02E6A280F00DE41FB /* SQLiteData in Frameworks */,
+ CA2BDE2C2E71C472000974D3 /* SQLiteData in Frameworks */,
DCBE8A142D4842BF0071F499 /* CasePaths in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -193,6 +219,7 @@
CA5E46972DEBFE410069E0F8 /* RemindersTests */,
DCBE89CD2D483FB90071F499 /* SyncUps */,
CAD0017E2D874E6F00FA977A /* SyncUpTests */,
+ CA2BDD9E2E71C30B000974D3 /* CloudKitDemo */,
CAF837022D4735C00047AEB5 /* Frameworks */,
CAF836992D4735620047AEB5 /* Products */,
);
@@ -207,6 +234,7 @@
DCBE89CC2D483FB90071F499 /* SyncUps.app */,
CAD0017D2D874E6F00FA977A /* SyncUpTests.xctest */,
CA5E46962DEBFE410069E0F8 /* RemindersTests.xctest */,
+ CA2BDD9D2E71C30B000974D3 /* CloudKitDemo.app */,
);
name = Products;
sourceTree = "";
@@ -214,6 +242,7 @@
CAF837022D4735C00047AEB5 /* Frameworks */ = {
isa = PBXGroup;
children = (
+ CA2BDE272E71C42B000974D3 /* sqlite-data */,
);
name = Frameworks;
sourceTree = "";
@@ -221,6 +250,29 @@
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
+ CA2BDD9C2E71C30B000974D3 /* CloudKitDemo */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = CA2BDDA72E71C30D000974D3 /* Build configuration list for PBXNativeTarget "CloudKitDemo" */;
+ buildPhases = (
+ CA2BDD992E71C30B000974D3 /* Sources */,
+ CA2BDD9A2E71C30B000974D3 /* Frameworks */,
+ CA2BDD9B2E71C30B000974D3 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ fileSystemSynchronizedGroups = (
+ CA2BDD9E2E71C30B000974D3 /* CloudKitDemo */,
+ );
+ name = CloudKitDemo;
+ packageProductDependencies = (
+ CA2BDE292E71C469000974D3 /* SQLiteData */,
+ );
+ productName = CloudKitDemo;
+ productReference = CA2BDD9D2E71C30B000974D3 /* CloudKitDemo.app */;
+ productType = "com.apple.product-type.application";
+ };
CA5E46952DEBFE410069E0F8 /* RemindersTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = CA5E469C2DEBFE420069E0F8 /* Build configuration list for PBXNativeTarget "RemindersTests" */;
@@ -289,7 +341,7 @@
name = CaseStudies;
packageProductDependencies = (
CA2908C82D4AF70E003F165F /* UIKitNavigation */,
- DC9A3DDD2E6A280700DE41FB /* SQLiteData */,
+ CA2BDE2F2E71C480000974D3 /* SQLiteData */,
);
productName = Examples;
productReference = CAF836982D4735620047AEB5 /* CaseStudies.app */;
@@ -337,7 +389,7 @@
packageProductDependencies = (
CA14DBC82DA884C400E36852 /* CasePaths */,
CA5E46902DEBB8570069E0F8 /* SwiftUINavigation */,
- CA6A1D232E68A0A600604D6A /* SQLiteData */,
+ CA2BDE2D2E71C479000974D3 /* SQLiteData */,
);
productName = Reminders;
productReference = CAF836D82D4735AB0047AEB5 /* Reminders.app */;
@@ -363,7 +415,7 @@
DCBE8A132D4842BF0071F499 /* CasePaths */,
DCF267382D48437300B680BE /* SwiftUINavigation */,
DC5FA7472D4C63D60082743E /* DependenciesMacros */,
- DC9A3DDF2E6A280F00DE41FB /* SQLiteData */,
+ CA2BDE2B2E71C472000974D3 /* SQLiteData */,
);
productName = SyncUps;
productReference = DCBE89CC2D483FB90071F499 /* SyncUps.app */;
@@ -379,6 +431,9 @@
LastSwiftUpdateCheck = 1640;
LastUpgradeCheck = 1620;
TargetAttributes = {
+ CA2BDD9C2E71C30B000974D3 = {
+ CreatedOnToolsVersion = 16.4;
+ };
CA5E46952DEBFE410069E0F8 = {
CreatedOnToolsVersion = 16.4;
TestTargetID = CAF836D72D4735AB0047AEB5;
@@ -416,7 +471,7 @@
DCF267372D48437300B680BE /* XCRemoteSwiftPackageReference "swift-navigation" */,
DC5FA7462D4C63D60082743E /* XCRemoteSwiftPackageReference "swift-dependencies" */,
CA5E47052DECEF0F0069E0F8 /* XCRemoteSwiftPackageReference "swift-snapshot-testing" */,
- DCD9AC892E02176700FB20F8 /* XCLocalSwiftPackageReference ".." */,
+ CA2BDE282E71C469000974D3 /* XCLocalSwiftPackageReference ".." */,
);
preferredProjectObjectVersion = 77;
productRefGroup = CAF836992D4735620047AEB5 /* Products */;
@@ -429,11 +484,19 @@
CA5E46952DEBFE410069E0F8 /* RemindersTests */,
DCBE89CB2D483FB90071F499 /* SyncUps */,
CAD0017C2D874E6F00FA977A /* SyncUpTests */,
+ CA2BDD9C2E71C30B000974D3 /* CloudKitDemo */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
+ CA2BDD9B2E71C30B000974D3 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
CA5E46942DEBFE410069E0F8 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@@ -479,6 +542,13 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
+ CA2BDD992E71C30B000974D3 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
CA5E46922DEBFE410069E0F8 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -542,6 +612,68 @@
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
+ CA2BDDA52E71C30D000974D3 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CODE_SIGN_ENTITLEMENTS = CloudKitDemo/CloudKitDemo.entitlements;
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = VFRXY8HC3H;
+ ENABLE_PREVIEWS = YES;
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_FILE = CloudKitDemo/Info.plist;
+ INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
+ INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
+ INFOPLIST_KEY_UILaunchScreen_Generation = YES;
+ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+ IPHONEOS_DEPLOYMENT_TARGET = 18.5;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = co.pointfree.SQLiteData.CloudKitDemo;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_EMIT_LOC_STRINGS = YES;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ CA2BDDA62E71C30D000974D3 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CODE_SIGN_ENTITLEMENTS = CloudKitDemo/CloudKitDemo.entitlements;
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = VFRXY8HC3H;
+ ENABLE_PREVIEWS = YES;
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_FILE = CloudKitDemo/Info.plist;
+ INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
+ INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
+ INFOPLIST_KEY_UILaunchScreen_Generation = YES;
+ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+ IPHONEOS_DEPLOYMENT_TARGET = 18.5;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = co.pointfree.SQLiteData.CloudKitDemo;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_EMIT_LOC_STRINGS = YES;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
CA5E469D2DEBFE420069E0F8 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -938,6 +1070,15 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
+ CA2BDDA72E71C30D000974D3 /* Build configuration list for PBXNativeTarget "CloudKitDemo" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ CA2BDDA52E71C30D000974D3 /* Debug */,
+ CA2BDDA62E71C30D000974D3 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
CA5E469C2DEBFE420069E0F8 /* Build configuration list for PBXNativeTarget "RemindersTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
@@ -1004,9 +1145,9 @@
/* End XCConfigurationList section */
/* Begin XCLocalSwiftPackageReference section */
- DCD9AC892E02176700FB20F8 /* XCLocalSwiftPackageReference ".." */ = {
+ CA2BDE282E71C469000974D3 /* XCLocalSwiftPackageReference ".." */ = {
isa = XCLocalSwiftPackageReference;
- relativePath = "..";
+ relativePath = ..;
};
/* End XCLocalSwiftPackageReference section */
@@ -1056,6 +1197,25 @@
package = DCF267372D48437300B680BE /* XCRemoteSwiftPackageReference "swift-navigation" */;
productName = UIKitNavigation;
};
+ CA2BDE292E71C469000974D3 /* SQLiteData */ = {
+ isa = XCSwiftPackageProductDependency;
+ productName = SQLiteData;
+ };
+ CA2BDE2B2E71C472000974D3 /* SQLiteData */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = CA2BDE282E71C469000974D3 /* XCLocalSwiftPackageReference ".." */;
+ productName = SQLiteData;
+ };
+ CA2BDE2D2E71C479000974D3 /* SQLiteData */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = CA2BDE282E71C469000974D3 /* XCLocalSwiftPackageReference ".." */;
+ productName = SQLiteData;
+ };
+ CA2BDE2F2E71C480000974D3 /* SQLiteData */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = CA2BDE282E71C469000974D3 /* XCLocalSwiftPackageReference ".." */;
+ productName = SQLiteData;
+ };
CA5E46902DEBB8570069E0F8 /* SwiftUINavigation */ = {
isa = XCSwiftPackageProductDependency;
package = DCF267372D48437300B680BE /* XCRemoteSwiftPackageReference "swift-navigation" */;
@@ -1076,11 +1236,6 @@
package = DC5FA7462D4C63D60082743E /* XCRemoteSwiftPackageReference "swift-dependencies" */;
productName = DependenciesTestSupport;
};
- CA6A1D232E68A0A600604D6A /* SQLiteData */ = {
- isa = XCSwiftPackageProductDependency;
- package = DCD9AC892E02176700FB20F8 /* XCLocalSwiftPackageReference ".." */;
- productName = SQLiteData;
- };
CAD001862D874F1F00FA977A /* DependenciesTestSupport */ = {
isa = XCSwiftPackageProductDependency;
package = DC5FA7462D4C63D60082743E /* XCRemoteSwiftPackageReference "swift-dependencies" */;
@@ -1091,16 +1246,6 @@
package = DC5FA7462D4C63D60082743E /* XCRemoteSwiftPackageReference "swift-dependencies" */;
productName = DependenciesMacros;
};
- DC9A3DDD2E6A280700DE41FB /* SQLiteData */ = {
- isa = XCSwiftPackageProductDependency;
- package = DCD9AC892E02176700FB20F8 /* XCLocalSwiftPackageReference ".." */;
- productName = SQLiteData;
- };
- DC9A3DDF2E6A280F00DE41FB /* SQLiteData */ = {
- isa = XCSwiftPackageProductDependency;
- package = DCD9AC892E02176700FB20F8 /* XCLocalSwiftPackageReference ".." */;
- productName = SQLiteData;
- };
DCBE8A132D4842BF0071F499 /* CasePaths */ = {
isa = XCSwiftPackageProductDependency;
package = DCBE8A122D4842BF0071F499 /* XCRemoteSwiftPackageReference "swift-case-paths" */;
diff --git a/Examples/Examples.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Examples/Examples.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
index f68ebba6..e7386aee 100644
--- a/Examples/Examples.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
+++ b/Examples/Examples.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -1,5 +1,5 @@
{
- "originHash" : "22fb924569f92610b5675a628f98b8864244fe7f2f1702deb956f693c2598118",
+ "originHash" : "3c33240501a0679d36175ebd2f677189bf28a044e6a74e224c59f016319f653e",
"pins" : [
{
"identity" : "combine-schedulers",
@@ -73,6 +73,24 @@
"version" : "1.9.4"
}
},
+ {
+ "identity" : "swift-docc-plugin",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/apple/swift-docc-plugin",
+ "state" : {
+ "revision" : "3e4f133a77e644a5812911a0513aeb7288b07d06",
+ "version" : "1.4.5"
+ }
+ },
+ {
+ "identity" : "swift-docc-symbolkit",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/swiftlang/swift-docc-symbolkit",
+ "state" : {
+ "revision" : "b45d1f2ed151d057b54504d653e0da5552844e34",
+ "version" : "1.0.0"
+ }
+ },
{
"identity" : "swift-identified-collections",
"kind" : "remoteSourceControl",
diff --git a/Examples/Examples.xcodeproj/xcshareddata/xcschemes/CloudKitDemo.xcscheme b/Examples/Examples.xcodeproj/xcshareddata/xcschemes/CloudKitDemo.xcscheme
deleted file mode 100644
index 46a630af..00000000
--- a/Examples/Examples.xcodeproj/xcshareddata/xcschemes/CloudKitDemo.xcscheme
+++ /dev/null
@@ -1,91 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Examples/README.md b/Examples/README.md
index 26b2754f..50d85ea4 100644
--- a/Examples/README.md
+++ b/Examples/README.md
@@ -7,6 +7,14 @@ with [SQLiteData](http://github.com/pointfreeco/sqlite-data).
Demonstrates how to solve some common application problems in an isolated environment, in
both SwiftUI and UIKit. Things like animations, dynamic queries, database transactions, and more.
+* **CloudKitDemo**
+
A simplified demo that shows how to synchronize a SQLite database to CloudKit and how to
+ share records with other iCloud users. See our dedicated articles on [CloudKit Synchronization]
+ and [CloudKit Sharing] for more information.
+
+ [CloudKit Synchronization]: https://swiftpackageindex.com/pointfreeco/sqlite-data/main/documentation/sqlitedata/cloudkit
+ [CloudKit Sharing]: https://swiftpackageindex.com/pointfreeco/sqlite-data/main/documentation/sqlitedata/cloudkitsharing
+
* **Reminders**
A rebuild of Apple's [Reminders][reminders-app-store] app that uses a SQLite database to
model the reminders, lists and tags. It features many advanced queries, such as searching, stats
@@ -15,6 +23,8 @@ with [SQLiteData](http://github.com/pointfreeco/sqlite-data).
* **SyncUps**
This application is a faithful reconstruction of one of Apple's more interesting sample
projects, called [Scrumdinger][scrumdinger], and uses SQLite to persist the data for meetings.
+ We have also added CloudKit synchronization so that all changes are automatically made available
+ on all of the user's devices.
[scrumdinger]: https://developer.apple.com/tutorials/app-dev-training/getting-started-with-scrumdinger
[reminders-app-store]: https://apps.apple.com/us/app/reminders/id1108187841
diff --git a/README.md b/README.md
index 24180b55..29898d0e 100644
--- a/README.md
+++ b/README.md
@@ -346,16 +346,28 @@ for data and keep your views up-to-date when data in the database changes, and y
This repo comes with _lots_ of examples to demonstrate how to solve common and complex problems with
SQLiteData. Check out [this](./Examples) directory to see them all, including:
- * [Case Studies](./Examples/CaseStudies): A number of case studies demonstrating the built-in
- features of the library.
-
- * [SyncUps](./Examples/SyncUps): We also rebuilt Apple's [Scrumdinger][] demo application using
- modern, best practices for SwiftUI development, including using this library to query and
- persist state using SQLite.
-
- * [Reminders](./Examples/Reminders): A rebuild of Apple's [Reminders][reminders-app-store] app
- that uses a SQLite database to model the reminders, lists and tags. It features many advanced
- queries, such as searching, and stats aggregation.
+* [**Case Studies**](./Examples/CaseStudies)
+
Demonstrates how to solve some common application problems in an isolated environment, in
+ both SwiftUI and UIKit. Things like animations, dynamic queries, database transactions, and more.
+
+* [**CloudKitDemo**](./Examples/CloudKitDemo)
+
A simplified demo that shows how to synchronize a SQLite database to CloudKit and how to
+ share records with other iCloud users. See our dedicated articles on [CloudKit Synchronization]
+ and [CloudKit Sharing] for more information.
+
+ [CloudKit Synchronization]: https://swiftpackageindex.com/pointfreeco/sqlite-data/main/documentation/sqlitedata/cloudkit
+ [CloudKit Sharing]: https://swiftpackageindex.com/pointfreeco/sqlite-data/main/documentation/sqlitedata/cloudkitsharing
+
+* [**Reminders**](./Examples/Reminders)
+
A rebuild of Apple's [Reminders][reminders-app-store] app that uses a SQLite database to
+ model the reminders, lists and tags. It features many advanced queries, such as searching, stats
+ aggregation, and multi-table joins. It also features CloudKit synchronization and sharing.
+
+* [**SyncUps**](./Examples/SyncUps)
+
This application is a faithful reconstruction of one of Apple's more interesting sample
+ projects, called [Scrumdinger][scrumdinger], and uses SQLite to persist the data for meetings.
+ We have also added CloudKit synchronization so that all changes are automatically made available
+ on all of the user's devices.
[Scrumdinger]: https://developer.apple.com/tutorials/app-dev-training/getting-started-with-scrumdinger
[reminders-app-store]: https://apps.apple.com/us/app/reminders/id1108187841
diff --git a/Sources/SQLiteData/CloudKit/SyncEngine.swift b/Sources/SQLiteData/CloudKit/SyncEngine.swift
index a828ab90..a203ec61 100644
--- a/Sources/SQLiteData/CloudKit/SyncEngine.swift
+++ b/Sources/SQLiteData/CloudKit/SyncEngine.swift
@@ -89,7 +89,9 @@
repeat (each T1).PrimaryKey.QueryOutput: IdentifierStringConvertible,
repeat (each T2).PrimaryKey.QueryOutput: IdentifierStringConvertible
{
- let containerIdentifier = containerIdentifier ?? CKContainer.default().containerIdentifier
+ let containerIdentifier =
+ containerIdentifier
+ ?? ModelConfiguration(groupContainer: .automatic).cloudKitContainerIdentifier
var allTables: [any PrimaryKeyedTable.Type] = []
var allPrivateTables: [any PrimaryKeyedTable.Type] = []
@@ -1808,7 +1810,7 @@
public func attachMetadatabase(containerIdentifier: String? = nil) throws {
let containerIdentifier =
containerIdentifier
- ?? CKContainer.default().containerIdentifier
+ ?? ModelConfiguration(groupContainer: .automatic).cloudKitContainerIdentifier
guard let containerIdentifier else {
throw SyncEngine.SchemaError(