### Complete Database Setup and Migration Function Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/PreparingDatabase.md This is the complete function for setting up the database connection, including configuration, conditional debugging trace, environment-specific database pool/queue creation, and applying migrations. ```swift import OSLog import SharingGRDB func appDatabase() throws -> any DatabaseWriter { @Dependency(\.context) var context var configuration = Configuration() configuration.foreignKeysEnabled = true #if DEBUG configuration.prepareDatabase { db in db.trace(options: .profile) { if context == .preview { print("\($0.expandedDescription)") } else { logger.debug("\($0.expandedDescription)") } } } #endif let database: any DatabaseWriter if context == .live { let path = URL.documentsDirectory.appending(component: "db.sqlite").path() logger.info("open \(path)") database = try DatabasePool(path: path, configuration: configuration) } else if context == .test { let path = URL.temporaryDirectory.appending(component: "\(UUID().uuidString)-db.sqlite").path() database = try DatabasePool(path: path, configuration: configuration) } else { database = try DatabaseQueue(configuration: configuration) } var migrator = DatabaseMigrator() #if DEBUG migrator.eraseDatabaseOnSchemaChange = true #endif migrator.registerMigration("Create tables") { db in // ... } try migrator.migrate(database) return database } private let logger = Logger(subsystem: "MyApp", category: "Database") ``` -------------------------------- ### Configure Default Database in SharingGRDB Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/SharingGRDBCore.md Provide the default database connection at app launch using `prepareDependencies`. This is analogous to SwiftData's `ModelContainer` setup. ```swift // SharingGRDB @main struct MyApp: App { init() { prepareDependencies { // Create/migrate a database connection let db = try! DatabaseQueue(/* ... */) $0.defaultDatabase = db } } // ... } ``` -------------------------------- ### Fetching Data in @Observable Models: SharingGRDB vs. SwiftData Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md Shows how SharingGRDB's @FetchAll works seamlessly within an @Observable model, while SwiftData requires manual fetching and observation setup. ```swift // SharingGRDB @Observable class FeatureModel { @ObservationIgnored @FetchAll(Item.order(by: \.title)) var items // ... } ``` ```swift // SwiftData @Observable class FeatureModel { var modelContext: ModelContext var items = [Item]() var observer: (any NSObjectProtocol)! init(modelContext: ModelContext) { self.modelContext = modelContext observer = NotificationCenter.default.addObserver( forName: ModelContext.willSave, object: modelContext, queue: nil ) { [weak self] _ in self?.fetchItems() } fetchItems() } deinit { NotificationCenter.default.removeObserver(observer) } func fetchItems() { do { items = try modelContext.fetch( FetchDescriptor(sortBy: [SortDescriptor(\Item.title)]) ) } catch { // Handle error } } // ... } ``` -------------------------------- ### Efficient Dynamic Query with SharingGRDB Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/DynamicQueries.md This example shows how to offload data processing to SQLite by modifying the query dynamically. It uses the `$items.load` method to apply filters, sorting, and limits directly in the database query, improving performance. ```swift struct ContentView: View { @FetchAll var items: [Item] @State var filterDate: Date? @State var order: SortOrder = .reverse var body: some View { List { // ... } .task(id: [filter, ordering] as [AnyHashable]) { await updateQuery() } } private func updateQuery() async { do { try await $items.load( Items .where { $0.timestamp > #bind(filterDate ?? .distantPast) } .order { if order == .forward { $0.timestamp } else { $0.timestamp.desc() } } .limit(10) ) } catch { // Handle error... } } // ... } ``` -------------------------------- ### Inefficient In-Memory Filtering and Sorting Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/DynamicQueries.md This example demonstrates fetching all items into memory and then filtering, sorting, and truncating them using Swift's collection algorithms. This approach is inefficient for large datasets as it loads and processes all rows in memory. ```swift struct ContentView: View { @FetchAll var items: [Item] @State var filterDate: Date? @State var order: SortOrder = .reverse var displayedItems: [Item] { items .filter { $0.timestamp > filterDate ?? .distantPast } .sorted { order == .forward ? $0.timestamp < $1.timestamp : $0.timestamp > $1.timestamp } .prefix(10) } // ... } ``` -------------------------------- ### Fetch Sorted Records Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/Fetching.md Fetch records and sort them by a specific property using the query building APIs. This example sorts reminders by their title. ```swift @FetchAll(Reminder.order(by: \.title)) var reminders ``` -------------------------------- ### Fetch Filtered and Sorted Records Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/Fetching.md Combine filtering and sorting to fetch specific records. This example fetches completed reminders, sorted by title in descending order. ```swift @FetchAll( Reminder.where(\.isCompleted).order { $0.title.desc() } ) var completedReminders ``` -------------------------------- ### Set up External Storage with SharingGRDB Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md Set up the default database for SharingGRDB at the app's entry point using prepareDependencies. This involves creating or migrating the SQLite database. ```swift // SharingGRDB @main struct MyApp: App { init() { prepareDependencies { // Create/migrate a database let db = try! DatabaseQueue(/* ... */) $0.defaultDatabase = db } } // ... } ``` -------------------------------- ### Create Database Connection for Live Environment Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/PreparingDatabase.md Constructs a database connection for a file path in the documents directory. Includes debug tracing for database operations. ```swift func appDatabase() throws -> any DatabaseWriter { @Dependency(\.context) var context var configuration = Configuration() configuration.foreignKeysEnabled = true #if DEBUG configuration.prepareDatabase { db in db.trace(options: .profile) { if context == .preview { print("\($0.expandedDescription)") } else { logger.debug("\($0.expandedDescription)") } } } #endif let path = URL.documentsDirectory.appending(component: "db.sqlite").path() logger.info("open \(path)") let database = try DatabasePool(path: path, configuration: configuration) return database } ``` -------------------------------- ### Prepare Database in Xcode Previews Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/PreparingDatabase.md Ensure your database connection is prepared for Xcode previews by calling `prepareDependencies` within the preview provider. This allows previews to function correctly with database access. ```swift #Preview { let _ = prepareDependencies { $0.defaultDatabase = try! appDatabase() } // ... } ``` -------------------------------- ### Fetching Data: SharingGRDB vs. SwiftData Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md Demonstrates fetching all items, ordered by title, using SharingGRDB's @FetchAll and SwiftData's @Query. ```swift // SharingGRDB struct ItemsView: View { @FetchAll(Item.order(by: \.title)) var items var body: some View { ForEach(items) { item in Text(item.name) } } } ``` ```swift // SwiftData struct ItemsView: View { @Query(sort: \Item.title) var items: [Item] var body: some View { ForEach(items) { item in Text(item.name) } } } ``` -------------------------------- ### Prepare Database in SwiftUI App Entry Point Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/PreparingDatabase.md Set the default database connection within the `init` method of your SwiftUI `App` conformance. This ensures dependencies are prepared early. ```swift import SharingGRDB import SwiftUI @main struct MyApp: App { init() { prepareDependencies { $0.defaultDatabase = try! appDatabase() } } // ... } ``` -------------------------------- ### Fetch Initialization and Loading Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Extensions/Fetch.md This section covers the various initializers for Fetch requests and the methods used to load data from the database. ```APIDOC ## Fetch Initialization and Loading This section details how to initialize and use `Fetch` requests to retrieve data. ### Initializers - `init(wrappedValue:_:database:)` - `init(_:database:)` - `init(database:)` - `init(wrappedValue:)` - `init(wrappedValue:_:database:animation:)` - `init(wrappedValue:_:database:scheduler:)` ### Loading Data - `load(_:database:)` - `load(_:database:animation:)` - `load(_:database:scheduler:)` ### Related Types - `FetchKeyRequest` - `FetchKey` - `FetchKeyID` ``` -------------------------------- ### SwiftUI Integration Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Extensions/FetchAll.md Initializers and methods for integrating FetchAll with SwiftUI, including animation support. ```APIDOC ## SwiftUI Integration ### Initializers - ``init(wrappedValue:database:animation:)`` - ``init(wrappedValue:_:database:animation:)`` ### Methods - ``load(_:database:animation:)`` ``` -------------------------------- ### Set up External Storage with SwiftData Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md Set up the ModelContainer for SwiftData at the app's entry point. The container is then propagated through the environment for use in SwiftUI views. ```swift // SwiftData @main struct MyApp: App { let container = { // Create/configure a container try! ModelContainer(/* ... */) }() var body: some Scene { WindowGroup { ContentView() .modelContainer(container) } } } ``` -------------------------------- ### FetchOne Initializers Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Extensions/FetchOne.md Initializers for the FetchOne property wrapper, allowing for direct value assignment, database association, and optional initial values. ```APIDOC ## FetchOne Initializers ### Description Initializers for the FetchOne property wrapper. ### Initializers - `init(wrappedValue:database:)` - `init(database:)` - `init(wrappedValue:_:database:)` ``` -------------------------------- ### Handle Different Application Contexts for Database Connection Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/PreparingDatabase.md Adapts database connection based on the application context (live, test, preview). Uses temporary directory for tests and in-memory for previews. ```swift func appDatabase() -> any DatabaseWriter { @Dependency(\.context) var context let database: any DatabaseWriter if context == .live { let path = URL.documentsDirectory.appending(component: "db.sqlite").path() logger.info("open \(path)") database = try DatabasePool(path: path, configuration: configuration) } else if context == .test { let path = URL.temporaryDirectory.appending(component: "\(UUID().uuidString)-db.sqlite").path() database = try DatabasePool(path: path, configuration: configuration) } else { database = try DatabaseQueue(configuration: configuration) } return database } ``` -------------------------------- ### Prepare Database in UIKit App Delegate Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/PreparingDatabase.md Configure the default database connection in the `applicationDidFinishLaunching` method of your `AppDelegate` for UIKit applications. This is a common place to initialize app-wide dependencies. ```swift import SharingGRDB import UIKit class AppDelegate: NSObject, UIApplicationDelegate { func applicationDidFinishLaunching(_ application: UIApplication) { prepareDependencies { $0.defaultDatabase = try! appDatabase() } } // ... } ``` -------------------------------- ### Dynamic Queries with SharingGRDB Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md Demonstrates how to perform dynamic queries in SwiftUI using SharingGRDB's `@FetchAll` and the `.task` modifier to update search results based on user input. ```swift struct ItemsView: View { @State var searchText = "" @FetchAll var items: [Item] var body: some View { ForEach(items) { item in Text(item.name) } .searchable(text: $searchText) .task(id: searchText) { await updateSearchQuery() } } func updateSearchQuery() { await $items.load( .fetchAll( Item.where { $0.title.contains(searchText) } ) ) } } ``` -------------------------------- ### Create Table and Fetch Players Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/StructuredQueriesGRDBCore/Documentation.docc/StructuredQueriesGRDBCore.md Demonstrates creating a 'players' table and then fetching players with a score greater than 10 using StructuredQueries and GRDB. ```swift @Table struct Player { let id: Int var name = "" var score = 0 } try #sql( """ CREATE TABLE players ( id INTEGER PRIMARY KEY, name TEXT, score INTEGER ) """ ) .execute(db) let players = Player .where { $0.score > 10 } .fetchAll(db) // SELECT … FROM "players" // WHERE "players"."score" > 10 ``` -------------------------------- ### Creating Data with SharingGRDB Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md Illustrates how to insert a new row into the database using the `write` and `insert` methods provided by SharingGRDB. ```swift @Dependency(\.defaultDatabase) var database try database.write { db in try Item.insert(Item(/* ... */)) .execute(db) } ``` -------------------------------- ### Fetching Data Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Extensions/FetchAll.md Initializers and methods for loading data using the FetchAll extension. ```APIDOC ## Fetching Data ### Initializers - ``init(wrappedValue:database:)`` - ``init(wrappedValue:_:database:)`` ### Methods - ``load(_:database:)`` ``` -------------------------------- ### Registering Table Creation Migrations with SQL Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/PreparingDatabase.md This snippet demonstrates how to register a migration that creates two tables, 'remindersLists' and 'reminders', using plain SQL strings within the #sql macro. ```swift migrator.registerMigration("Create tables") { db in try #sql(""" CREATE TABLE "remindersLists"( "id" INT NOT NULL PRIMARY KEY AUTOINCREMENT, "title" TEXT NOT NULL ) STRICT """) .execute(db) try #sql(""" CREATE TABLE "reminders"( "id" INT NOT NULL PRIMARY KEY AUTOINCREMENT, "isCompleted" INT NOT NULL DEFAULT 0, "title" TEXT NOT NULL, "remindersListID" INT NOT NULL REFERENCES "remindersLists"("id") ON DELETE CASCADE ) STRICT """) .execute(db) } ``` -------------------------------- ### FetchOne SwiftUI Integration Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Extensions/FetchOne.md Initializers and methods for integrating FetchOne with SwiftUI, including animation support. ```APIDOC ## FetchOne SwiftUI Integration ### Description Integrates FetchOne with SwiftUI, providing animation options during data loading. ### Initializers - `init(wrappedValue:database:animation:)` - `init(wrappedValue:_:database:animation:)` ### Methods - `load(_:database:animation:)` ``` -------------------------------- ### Fetch Count with SQL and @FetchOne Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/Fetching.md Execute raw SQL queries safely with the `#sql` macro within `@FetchOne` to fetch aggregate data. A default value must be provided. ```swift @FetchOne(#sql("SELECT count(*) FROM reminders WHERE isCompleted")) var completedRemindersCount = 0 ``` -------------------------------- ### Prepare Database in Tests Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/PreparingDatabase.md Use the `.dependency` testing trait to set the default database connection for your tests. This isolates test environments and ensures predictable database behavior. ```swift @Test(.dependency(\.defaultDatabase, try appDatabase())) func feature() { // ... } ``` -------------------------------- ### Advanced Fetching with SharingGRDB Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/SharingGRDBCore.md Demonstrates various ways to fetch data using `@FetchAll` with ordering and filtering. SharingGRDB offers more direct control over queries compared to SwiftData's `@Query`. ```swift @FetchAll var items: [Item] @FetchAll(Item.order(by: \.title)) var items @FetchAll(Item.where(\.isInStock)) var items @FetchOne(Item.count()) var inStockItemsCount = 0 ``` -------------------------------- ### FetchKeyRequest Query (0.1.0) Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/MigrationGuides/MigratingTo0.2.md Before version 0.2.0, queries could be defined by conforming to FetchKeyRequest, using GRDB's query builder. ```swift struct CompletedReminders: FetchKeyRequest { func fetch(_ db: Database) throws -> [Reminder] { Reminder.all() .where(Column("isCompleted")) .order(Column("title")) } } @SharedReader(.fetch(CompletedReminders())) var completedReminders ``` -------------------------------- ### Migrating Database with GRDB Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/PreparingDatabase.md This snippet shows how to create a DatabaseMigrator, register a migration, and apply it to the database connection. It includes conditional erasing of the database on schema changes for debugging. ```swift func appDatabase() throws -> any DatabaseWriter { @Dependency(\.context) var context var configuration = Configuration() configuration.foreignKeysEnabled = true #if DEBUG configuration.prepareDatabase { db in db.trace(options: .profile) { if context == .preview { print("\($0.expandedDescription)") } else { logger.debug("\($0.expandedDescription)") } } } #endif let database: any DatabaseWriter if context == .live { let path = URL.documentsDirectory.appending(component: "db.sqlite").path() logger.info("open \(path)") database = try DatabasePool(path: path, configuration: configuration) } else if context == .test { let path = URL.temporaryDirectory.appending(component: "\(UUID().uuidString)-db.sqlite").path() database = try DatabasePool(path: path, configuration: configuration) } else { database = try DatabaseQueue(configuration: configuration) } var migrator = DatabaseMigrator() #if DEBUG migrator.eraseDatabaseOnSchemaChange = true #endif migrator.registerMigration("Create tables") { db in // Execute SQL to create tables } try migrator.migrate(database) return database } ``` -------------------------------- ### Basic Fetching with SwiftData Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/SharingGRDBCore.md Shows the basic usage of SwiftData's `@Query` macro for fetching data. Note the lack of direct equivalents for filtering by boolean or counting without loading. ```swift @Query var items: [Item] @Query(sort: [SortDescriptor(\ .title)]) var items: [Item] // No @Query equivalent of filtering // by 'isInStock: Bool' // No @Query equivalent of counting // entries in database without loading // all entries. ``` -------------------------------- ### FetchOne Loading Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Extensions/FetchOne.md Methods for explicitly loading data into the FetchOne property wrapper. ```APIDOC ## FetchOne Loading ### Description Methods for explicitly loading data into the FetchOne property wrapper. ### Methods - `load(_:database:)` ``` -------------------------------- ### Creating Data with SwiftData Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md Shows how to insert a new row into the database using the `insert` method on the model context in SwiftData. ```swift @Environment(\.modelContext) var modelContext let newItem = Item(/* ... */) modelContext.insert(newItem) try modelContext.save() ``` -------------------------------- ### Updating Data with SharingGRDB Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md Demonstrates how to update an existing row in the database using the `write` and `update` methods provided by SharingGRDB. ```swift @Dependency(\.defaultDatabase) var database existingItem.title = "Computer" try database.write { db in try Item.update(existingItem).execute(db) } ``` -------------------------------- ### Fetch Multiple Records in Separate Transactions Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/Fetching.md Demonstrates fetching multiple sets of data using `@FetchOne` and `@FetchAll`, where each executes in its own database transaction. ```swift @FetchOne(Reminder.count()) var remindersCount = 0 @FetchAll(Reminder.where(\.isCompleted))) var completedReminders ``` -------------------------------- ### FetchOne Sharing Infrastructure Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Extensions/FetchOne.md Provides access to shared database readers and dynamic member subscription for advanced sharing scenarios. ```APIDOC ## FetchOne Sharing Infrastructure ### Description Provides access to shared database readers and supports dynamic member subscription for advanced sharing capabilities. ### Properties - `sharedReader`: Access to a shared database reader. ### Subscripts - `subscript(dynamicMember:)`: Allows dynamic member access for advanced functionalities. ``` -------------------------------- ### Fetch Using Raw SQL String Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/Fetching.md Execute a raw SQL string to populate data. The #sql macro provides protection against SQL injection. ```swift @FetchAll(#sql("SELECT * FROM reminders where isCompleted ORDER BY title DESC")) var completedReminders: [Reminder] ``` -------------------------------- ### Define Static App Database Connection Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/PreparingDatabase.md Define a static function that returns a connection to a local database stored on disk. This function should be defined at the module level where the schema is defined. ```swift func appDatabase() -> any DatabaseWriter { // ... } ``` -------------------------------- ### Dynamic Queries with SwiftData Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md Illustrates dynamic querying in SwiftUI with SwiftData, requiring two views: one for user input and another to hold the `@Query` with a dynamic predicate. ```swift struct ItemsView: View { @State var searchText = "" var body: some View { SearchResultsView( searchText: searchText ) .searchable(text: $searchText) } } struct SearchResultsView: View { @Query var items: [Item] init(searchText: String) { _items = Query( filter: #Predicate { $0.title.contains(searchText) } ) } var body: some View { ForEach(items) { item in Text(item.name) } } } ``` -------------------------------- ### Combine Integration Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Extensions/Fetch.md Details on how to integrate Fetch requests with Combine for reactive data streams. ```APIDOC ## Combine Integration This section explains how to use the `publisher` property to integrate `Fetch` requests with Combine. ### Publisher - `publisher`: Returns a publisher that emits the fetched data. ``` -------------------------------- ### FetchOne Combine Integration Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Extensions/FetchOne.md Provides a Combine publisher for observing changes in the FetchOne property wrapper. ```APIDOC ## FetchOne Combine Integration ### Description Exposes a Combine publisher to observe data changes and loading states. ### Properties - `publisher`: A publisher that emits the fetched data or loading states. ``` -------------------------------- ### Observe Database Changes in SwiftUI View Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/Observing.md Use the @FetchAll property wrapper in a SwiftUI View to automatically fetch and observe all items. The view re-renders when the queried data updates. ```swift struct ItemsView: View { @FetchAll var items: [Item] var body: some View { ForEach(items) { item in Text(item.name) } } } ``` -------------------------------- ### Enable Query Tracing in Debug Builds Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/PreparingDatabase.md Enable query tracing to log executed queries, useful for identifying long-running or unexpected queries. This is recommended only in debug builds and uses OSLog for live/simulator and print for previews. ```swift import OSLog import SharingGRDB func appDatabase() -> any DatabaseWriter { @Dependency(\.context) var context var configuration = Configuration() configuration.foreignKeysEnabled = true #if DEBUG configuration.prepareDatabase { db.trace(options: .profile) { if context == .preview { print($0.expandedDescription) } else { logger.debug($0.expandedDescription) } } } #endif } ``` ```swift private let logger = Logger(subsystem: "MyApp", category: "Database") ``` -------------------------------- ### Accessing Database Context with SwiftData Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md Demonstrates how to access the model context using the `@Environment` property wrapper in SwiftData. ```swift // SwiftData @Environment(\.modelContext) var modelContext ``` -------------------------------- ### Create 'items' Table with GRDB.swift Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md GRDB.swift requires explicit SQL statements to create tables, defining columns, types, and constraints like NOT NULL and default values. ```swift @Table struct Item { let id: Int var title = "" var isInStock = true } migrator.registerMigration("Create 'items' table") { db in try #sql( """ CREATE TABLE "items" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT, "title" TEXT NOT NULL, "isInStock" INTEGER NOT NULL DEFAULT 1 ) """ ) .execute(db) } ``` -------------------------------- ### Execute Custom FetchKeyRequest with @Fetch Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/Fetching.md Use the `@Fetch` property wrapper to execute a custom `FetchKeyRequest` and access its bundled data. A default value must be provided for the custom data type. ```swift @Fetch(Reminders()) var reminders = Reminders.Value() reminders.completedReminders // [Reminder(/* ... */), /* ... */] reminders.remindersCount // 100 ``` -------------------------------- ### Observe Database Changes in UIKit Collection View Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/Observing.md Utilize the .publisher property of a fetched value to observe database changes and update a UIKit collection view's data source using Combine. ```swift class ItemsViewController: UICollectionViewController { @FetchAll var items: [Item] override func viewDidLoad() { // Set up data source and cell registration... // Observe changes to items in order to update data source: $items.publisher.sink { items in guard let self else { return } dataSource.apply( NSDiffableDataSourceSnapshot(items: items), animatingDifferences: true ) } .store(in: &cancellables) } } ``` -------------------------------- ### FetchOne Custom Scheduling Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Extensions/FetchOne.md Allows specifying a custom scheduler for data loading operations. ```APIDOC ## FetchOne Custom Scheduling ### Description Enables the use of custom schedulers for asynchronous data loading. ### Initializers - `init(wrappedValue:database:scheduler:)` - `init(wrappedValue:_:database:scheduler:)` ### Methods - `load(_:database:scheduler:)` ``` -------------------------------- ### Fetching a Single Value Count with SharingGRDB Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md Illustrates fetching a single aggregate value, the count of in-stock items, using SharingGRDB's @FetchOne. ```swift @FetchOne(Item.where(\Item.isInStock).count()) var inStockItemsCount = 0 ``` -------------------------------- ### Custom Scheduling Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Extensions/FetchAll.md Initializers and methods for specifying a custom scheduler for data fetching operations. ```APIDOC ## Custom Scheduling ### Initializers - ``init(wrappedValue:database:scheduler:)`` - ``init(wrappedValue:_:database:scheduler:)`` ### Methods - ``load(_:database:scheduler:)`` ``` -------------------------------- ### Deleting Data with SharingGRDB Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md Illustrates how to delete an existing row from the database using the `write` and `delete` methods provided by SharingGRDB. ```swift @Dependency(\.defaultDatabase) var database try database.write { db in try Item.delete(existingItem).execute(db) } ``` -------------------------------- ### Type-Safe Query with @FetchAll (0.2.0) Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/MigrationGuides/MigratingTo0.2.md Version 0.2.0 introduces type-safe property wrappers like @FetchAll, allowing queries to be described directly and inline using the StructuredQueries library. ```swift @FetchAll(Reminder.where(\.isCompleted).order(by: \.title)) var completedReminders: [Reminder] ``` -------------------------------- ### Observe Database Changes in UIKit with Swift Navigation Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/Observing.md Use the 'observe' function from the Swift Navigation library to update a UIKit data source when database items change, avoiding direct Combine usage. ```swift override func viewDidLoad() { // Set up data source and cell registration... // Observe changes to items in order to update data source: observe { [weak self] in guard let self else { return } dataSource.apply( NSDiffableDataSourceSnapshot(items: items), animatingDifferences: true ) } } ``` -------------------------------- ### Updating Data with SwiftData Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md Shows how to update an existing row in the database by modifying its properties and then saving the model context in SwiftData. ```swift @Environment(\.modelContext) var modelContext existingItem.title = "Computer" try modelContext.save() ``` -------------------------------- ### Fetch Average Score Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/StructuredQueriesGRDBCore/Documentation.docc/StructuredQueriesGRDBCore.md Shows how to fetch the average score of players from a GRDB database using StructuredQueries. ```swift let averageScore = try Player .select { $0.score.avg() } .fetchOne(db) // SELECT avg("players"."score") FROM "players" ``` -------------------------------- ### GRDB.swift Manual Migration for Unique Index Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md Demonstrates a manual migration in GRDB.swift to add a unique index to the 'title' column in the 'items' table. It first deletes duplicate items and then creates the unique index using SQL. ```swift // SharingGRDB migrator.registerMigration("Make 'title' unique") { db in // 1️⃣ Delete all items that have duplicate title, keeping the first created one: try Item .delete() .where { !$0.id.in( Item .select { $0.id.min() } .group(by: \.title) ) } .execute() // 2️⃣ Create unique index try #sql( """ CREATE UNIQUE INDEX "items_title" ON "items" ("title") """ ) .execute(db) } ``` -------------------------------- ### Define Data Model with SwiftData Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/SharingGRDBCore.md Define your data model using Swift classes and the `@Model` attribute. This is the SwiftData approach. ```swift // SwiftData @Query var items: [Item] @Model class Item { var title: String var isInStock: Bool var notes: String init( title: String = "", isInStock: Bool = true, notes: String = "" ) { self.title = title self.isInStock = isInStock self.notes = notes } } ``` -------------------------------- ### Fetch All Records Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/Fetching.md Use the @FetchAll property wrapper to fetch all rows from a table. By default, it fetches records in their default order. ```swift @FetchAll var reminders: [Reminder] ``` -------------------------------- ### Configure Model Container in SwiftData Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/SharingGRDBCore.md Configure the `ModelContainer` for your SwiftData app. This is the SwiftData approach to setting up the data store. ```swift // SwiftData @main struct MyApp: App { let container = { // Create/configure a container try! ModelContainer(/* ... */) }() var body: some Scene { WindowGroup { ContentView() .modelContainer(container) } } } ``` -------------------------------- ### Combine Integration Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Extensions/FetchAll.md Provides a Combine publisher for observing data changes. ```APIDOC ## Combine Integration ### Publisher - ``publisher`` ``` -------------------------------- ### Observe Database Changes in @Observable Model Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/Observing.md Integrate @FetchAll with @Observable models for automatic data updates. Use @ObservationIgnored for the property wrapper within the @Observable class. ```swift @Observable class ItemsModel { @ObservationIgnored @FetchAll var items: [Item] } struct ItemsView: View { let model: ItemsModel var body: some View { ForEach(model.items) { item in Text(item.name) } } } ``` -------------------------------- ### Fetch Using Interpolated SQL String Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/Fetching.md Construct safe SQL strings using interpolations with the #sql macro. This method leverages static schema information to prevent typos and ensure type safety. ```swift @FetchAll( #sql( """ SELECT \(Reminder.columns) FROM \(Reminder.self) WHERE \(Reminder.isCompleted) ORDER BY \(Reminder.title) DESC """ ) ) var completedReminders: [Reminder] ``` -------------------------------- ### Deleting Data with SwiftData Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md Shows how to delete an existing row from the database by calling `delete` on the model context and then saving in SwiftData. ```swift @Environment(\.modelContext) var modelContext modelContext.delete(existingItem)) try modelContext.save() ``` -------------------------------- ### Define Custom FetchKeyRequest for Single Transaction Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/Fetching.md Define a custom `FetchKeyRequest` to bundle multiple database queries into a single transaction. The `Value` struct holds the fetched data. ```swift struct Reminders: FetchKeyRequest { struct Value { var completedReminders: [Reminder] = [] var remindersCount = 0 } func fetch(_ db: Database) throws -> Value { try Value( completedReminders: Reminder.where(\.isCompleted).fetchAll(db), remindersCount: Reminder.fetchCount(db) ) } } ``` -------------------------------- ### Sharing Infrastructure Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Extensions/FetchAll.md Provides access to shared reader instances and dynamic member access. ```APIDOC ## Sharing Infrastructure ### Accessors - ``sharedReader`` - ``subscript(dynamicMember:)`` ``` -------------------------------- ### SQL Query with @SharedReader (0.1.0) Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/MigrationGuides/MigratingTo0.2.md In version 0.1.0, queries were performed using hardcoded SQL strings within the @SharedReader property wrapper. ```swift @SharedReader(.fetchAll(sql: "SELECT * FROM reminders WHERE isCompleted ORDER BY title")) var completedReminders: [Reminder] ``` -------------------------------- ### SharingGRDB Fetching Associated Data with Join Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md Fetches sports and their associated team counts in a single query by joining tables. This is more efficient than multiple separate queries. ```swift @Selection struct SportWithTeamCount { let sport: Sport let teamCount: Int } @FetchAll( Sport .group(by: \.id) .leftJoin(Team.all) { $0.id.eq($1.sportID) } .select { SportWithTeamCount.Columns(sport: $0, teamCount: $1.count()) } ) var sportsWithTeamCounts ``` -------------------------------- ### Access Database Dependency in SharingGRDB Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/SharingGRDBCore.md Access the default database connection using the `@Dependency` property wrapper. This allows direct interaction with the SQLite database for writing operations. ```swift // SharingGRDB @Dependency(\ .defaultDatabase) var database try database.write { db in try Item.insert(Item(/* ... */)) .execute(db) } ``` -------------------------------- ### Fetch Data from Joined Tables Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/Fetching.md Perform a join between two tables and select specific columns into a @Selection struct. This is an efficient way to retrieve related data. ```swift @FetchAll( Reminder .join(RemindersList.all) { $0.remindersListID.eq($1.id) } .select { Record.Columns( reminderTitle: $0.title, remindersListTitle: $1.title ) } ) var records ``` -------------------------------- ### Fetch Single Record Count with @FetchOne Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/Fetching.md Use `@FetchOne` to fetch a single aggregate value, like a count, from the database. A default value must be provided. ```swift @FetchOne(Reminder.count()) var remindersCount = 0 ``` -------------------------------- ### FetchOne State Access Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Extensions/FetchOne.md Properties for accessing the current state of the FetchOne property wrapper, including the fetched value, loading status, and any errors. ```APIDOC ## FetchOne State Access ### Description Properties for accessing the current state of the FetchOne property wrapper. ### Properties - `wrappedValue`: The fetched data. - `projectedValue`: A projected value for further access. - `isLoading`: A boolean indicating if data is currently being loaded. - `loadError`: An optional error if loading failed. ``` -------------------------------- ### SwiftData Manual Migration for Unique Index Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md Illustrates a manual migration in SwiftData to enforce uniqueness on the 'title' attribute. This involves defining multiple schema versions, a migration plan, and custom migration logic to handle duplicate data. ```swift // SwiftData // 1️⃣ Create a type to conform to VersionedSchema and nest current Item inside: enum Schema1: VersionedSchema { static var versionIdentifier = Schema.Version(1, 0, 0) static var models: [any PersistentModel.Type] { [Item.self] } @Model class Item { var title = "" var isInStock = true } } // 2️⃣ Create type to conform to VersionedSchema: enum Schema2: VersionedSchema { static var versionIdentifier = Schema.Version(2, 0, 0) static var models: [any PersistentModel.Type] { [Item.self] } // 3️⃣ Duplicate Item type for new schema version with unique index: @Model class Item { @Attribute(.unique) var title = "" var isInStock = true } } // 4️⃣ Create a type alias for the newest Item schema: typealias Item = Schema2.Item // 5️⃣ Create a type to conform to the SchemaMigrationPlan protocol: enum MigrationPlan: SchemaMigrationPlan { static var schemas: [any VersionedSchema.Type] { [ Schema1.self, Schema2.self ] } // 6️⃣ Create MigrationStage values to implement the logic for migration from one schema // to the next: static var stages: [MigrationStage] { [ MigrationStage.custom( fromVersion: Schema1.self, toVersion: Schema2.self ) { context in // Delete items with duplicate titles, keeping the first created. // Fetch all items but hydrating only their titles: var fetchDescriptor = FetchDescriptor() fetchDescriptor.propertiesToFetch = [\.title] let items = try context.fetch(fetchDescriptor) // Keep track of unique titles so that we know when to delete an item: var uniqueTitles: Set = [] for item in items { if uniqueTitles.contains(item.title) { // If title is not unique, delete the item: context.delete(item) } else { // If title is unique, add it to the set so that we know to delete // items with this title: uniqueTitles.insert(item.title) } } try context.save() } didMigrate: { _ in } ] } } // 7️⃣ Create ModelContainer with migration plan in entry point of app: @main struct MyApp: App { let container: ModelContainer init() { container = try ModelContainer( for: Schema(versionedSchema: Schema2.self), migrationPlan: MigrationPlan.self ) } // ... } ``` -------------------------------- ### Define a Selection Structure Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/Fetching.md Create a struct decorated with @Selection to hold specific columns fetched from joined tables. This allows for efficient data retrieval. ```swift @Selection struct Record { let reminderTitle: String let remindersListTitle: String } ``` -------------------------------- ### Enable Foreign Key Constraints in Configuration Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/PreparingDatabase.md Configure the database to enable foreign key constraints for data integrity. This prevents deletion of rows that would leave other rows with invalid associations. ```swift var configuration = Configuration() configuration.foreignKeysEnabled = true ``` -------------------------------- ### Accessing Fetch State Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Extensions/Fetch.md Information on how to access the current state of a Fetch request, including loading status, errors, and the fetched value. ```APIDOC ## Accessing Fetch State This section describes how to access the state and projected values of a `Fetch` request. ### Properties - `wrappedValue`: The fetched data. - `projectedValue`: A projected value, likely for use in SwiftUI or Combine. - `isLoading`: A boolean indicating if the data is currently being loaded. - `loadError`: An optional error that occurred during loading. ``` -------------------------------- ### SwiftData Fetching Associated Data Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md Fetches Sport objects and then iterates to print the count of associated teams. This can lead to inefficient querying by executing multiple queries. ```swift let sport = try modelContext.fetch(FetchDescriptor()) for sport in sports { print("\(sport) has \(sport.teams.count) teams") } ``` -------------------------------- ### Fetch Filtered Count with @FetchOne Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/Fetching.md You can use `where` clauses with `@FetchOne` to fetch counts of filtered records. A default value must be provided. ```swift @FetchOne(Reminder.where(\.isCompleted).count()) var completedRemindersCount = 0 ``` -------------------------------- ### Accessing State Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Extensions/FetchAll.md Properties for accessing the loading state and any errors encountered during data fetching. ```APIDOC ## Accessing State ### Properties - ``wrappedValue`` - ``projectedValue`` - ``isLoading`` - ``loadError`` ``` -------------------------------- ### Define Data Model with SharingGRDB Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/SharingGRDBCore.md Define your data model using Swift structs and the `@Table` attribute. This is the SharingGRDB equivalent to SwiftData's `@Model` class. ```swift // SharingGRDB @FetchAll var items: [Item] @Table struct Item { let id: Int var title = "" var isInStock = true var notes = "" } ``` -------------------------------- ### Add 'description' Column with GRDB.swift Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md Adding a column in GRDB.swift involves an explicit ALTER TABLE statement, specifying the new column's name and type. ```swift @Table struct Item { let id: Int var title = "" var description = "" var isInStock = true } migrator.registerMigration("Add 'description' column to 'items'") { db in try #sql( """ ALTER TABLE "items" ADD COLUMN "description" TEXT """ ) .execute(db) } ``` -------------------------------- ### Define a Table Structure Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/Fetching.md Use the @Table macro to define a Swift struct that represents a database table. This enables the use of GRDB's query building APIs. ```swift @Table struct Reminder { let id: Int var title = "" var dueAt: Date? var isCompleted = false } ``` -------------------------------- ### SwiftData Querying Limitations with Boolean Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md Attempts to sort SwiftData Reminders by the boolean isCompleted property, which is not supported and will cause a runtime error. ```swift @Query(sort: [SortDescriptor(\. isCompleted)]) var reminders: [Reminder] // 🛑 ``` -------------------------------- ### Define Schema with SharingGRDB Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md Define a data schema using the @Table macro from StructuredQueries for type-safe and schema-safe queries in SharingGRDB. Works with struct data types. ```swift // SharingGRDB @Table struct Item { let id: Int var title = "" var isInStock = true var notes = "" } ``` -------------------------------- ### SharingGRDB Model with Boolean and Enum Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md Defines a SharingGRDB Reminder struct with boolean and optional enum properties. These types are fully supported for querying and ordering. ```swift @Table struct Reminder { var isCompleted = false var priority: Priority? enum Priority: Int, QueryBindable { case low, medium, high } } @FetchAll( Reminder .where { $0.priority == Priority.high } .order(by: \.isCompleted) ) var reminders ``` -------------------------------- ### SwiftData Querying Limitations with Enum Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md Attempts to filter SwiftData Reminders by the enum priority property, which will compile but crash at runtime. ```swift @Query(filter: #Predicate { $0.priority == Priority.high }) var highPriorityReminders: [Reminder] ``` -------------------------------- ### Access Model Context in SwiftData Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/SharingGRDBCore.md Access the `modelContext` using the `@Environment` property wrapper to perform operations like inserting new data. This is the standard SwiftData way to manage data. ```swift // SwiftData @Environment(\ .modelContext) var modelContext let newItem = Item(/* ... */) modelContext.insert(newItem) try modelContext.save() ``` -------------------------------- ### SwiftData Model with Boolean and Enum Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md Defines a SwiftData Reminder model with boolean and optional enum properties. SwiftData has limitations with sorting and filtering these types. ```swift @Model class Reminder { var isCompleted = false var priority: Priority? init(isCompleted: Bool = false, priority: Priority? = nil) { self.isCompleted = isCompleted self.priority = priority } enum Priority: Int, Codable { case low, medium, high } } ``` -------------------------------- ### SwiftData Workaround for Boolean and Enum Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md Models boolean and enum properties as integers to enable sorting and filtering in SwiftData. This sacrifices type safety and limits valid values. ```swift @Model class Reminder { var isCompleted = 0 var priority: Int? init(isCompleted: Int = 0, priority: Int? = nil) { self.isCompleted = isCompleted self.priority = priority } } @Query( filter: #Predicate { $0.priority == 2 }, sort: [SortDescriptor(\. isCompleted)] ) var highPriorityReminders: [Reminder] ``` -------------------------------- ### SwiftData Model with Associations Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md Defines a SwiftData Sport model with a relationship to Team. This requires both models to be classes. ```swift @Model class Sport { @Relationship(inverse: \Team.sport) var teams = [Team]() } @Model class Team { var sport: Sport } ``` -------------------------------- ### Define Schema with SwiftData Source: https://github.com/pointfreeco/sharing-grdb/blob/main/Sources/SharingGRDBCore/Documentation.docc/Articles/ComparisonWithSwiftData.md Define a data schema using the @Model macro for class data types in SwiftData. SwiftData provides a persistentIdentifier, so an explicit id field is not required. ```swift // SwiftData @Model class Item { var title: String var isInStock: Bool var notes: String init( title: String = "", isInStock: Bool = true, notes: String = "" ) { self.title = title self.isInStock = isInStock self.notes = notes } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.