Sqlite data
SQLiteData persistence library (Point-Free) - a fast SwiftData alternative using SQLite/GRDB. Use when working with SQLiteData, GRDB, type-safe SQL queries, @Table macro, @FetchAll/@FetchOne property wrappers, or migrating from SwiftData to SQLite-based persistence.From its SKILL.md
npx -y skills add onmyway133/skills --skill sqlite-dataAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
5.8 KB, as published. Nobody here has run it
SQLiteData
You are a SQLiteData expert. Apply these patterns when working with SQLite persistence using Point-Free's SQLiteData library.
When to Use
- Building apps with SQLite persistence using SQLiteData
- Migrating from SwiftData to SQLiteData
- Using GRDB with type-safe queries
- Implementing CloudKit sync with SQLite
- Working with @Table, @FetchAll, @FetchOne, or @Fetch
- Need better performance than SwiftData
- Need to work outside SwiftUI views (@Observable, UIKit)
Decision Tree
| Need | Reference |
|---|---|
| Define models with @Table macro | model-basics.md |
| Fetch data with @FetchAll/@FetchOne/@Fetch | fetching.md |
| Insert, update, delete data | queries-crud.md |
| Dynamic queries, search, FetchKeyRequest | dynamic-queries.md |
| Joins and multi-table queries | relationships-joins.md |
| Database setup, migrations, seeding | database-setup.md |
| CloudKit synchronization and sharing | cloudkit-sync.md |
| Testing patterns and utilities | testing.md |
| SwiftData comparison and migration | migration-comparison.md |
| Debug and troubleshoot | common-issues.md |
Core Principles
- Use @Table for persistent structs - Unlike SwiftData's @Model (classes only), @Table works with value types
- Use @Dependency(.defaultDatabase) for writes - Property wrappers are read-only; use dependency for mutations
- Property wrappers auto-observe changes - @FetchAll/@FetchOne automatically update when database changes
- Type-safe queries via StructuredQueries - Use fluent API or #sql macro for safe SQL
- Explicit database writes - No autosave; use
database.write { }for all mutations
Quick Reference
Basic Model
import SQLiteData
@Table
struct Reminder: Identifiable {
let id: UUID
var title = ""
var isCompleted = false
var dueDate: Date?
}
App Setup
@main
struct MyApp: App {
init() {
prepareDependencies {
$0.defaultDatabase = try! appDatabase()
}
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
func appDatabase() throws -> any DatabaseWriter {
let database = try defaultDatabase()
var migrator = DatabaseMigrator()
migrator.registerMigration("Create tables") { db in
try #sql("""
CREATE TABLE "reminders" (
"id" TEXT PRIMARY KEY NOT NULL,
"title" TEXT NOT NULL DEFAULT '',
"isCompleted" INTEGER NOT NULL DEFAULT 0,
"dueDate" TEXT
) STRICT
""").execute(db)
}
try migrator.migrate(database)
return database
}
Fetch in SwiftUI
struct ReminderList: View {
@FetchAll(Reminder.order(by: \.title))
var reminders
@FetchOne(Reminder.count())
var count = 0
var body: some View {
List(reminders) { reminder in
Text(reminder.title)
}
}
}
CRUD Operations
@Dependency(\.defaultDatabase) var database
// Create
try await database.write { db in
try Reminder.insert(Reminder(id: UUID(), title: "Buy milk"))
.execute(db)
}
// Read with filtering
@FetchAll(Reminder.where(\.isCompleted).order { $0.title.desc() })
var completedReminders
// Update
reminder.title = "Updated Title"
try await database.write { db in
try Reminder.update(reminder).execute(db)
}
// Delete
try await database.write { db in
try Reminder.delete(reminder).execute(db)
}
Dynamic Query with Search
struct SearchView: View {
@Fetch(RemindersRequest()) var data = RemindersRequest.Value()
@State var searchText = ""
var body: some View {
List(data.reminders) { reminder in
Text(reminder.title)
}
.searchable(text: $searchText)
.task(id: searchText) {
try? await $data.load(RemindersRequest(query: searchText)).task
}
}
}
struct RemindersRequest: FetchKeyRequest {
var query = ""
struct Value {
var reminders: [Reminder] = []
var count = 0
}
func fetch(_ db: Database) throws -> Value {
let filtered = Reminder
.where { $0.title.contains(query) }
.order(by: \.title)
return try Value(
reminders: filtered.fetchAll(db),
count: filtered.fetchCount(db)
)
}
}
References
- model-basics.md - @Table macro, columns, Draft types
- fetching.md - @FetchAll, @FetchOne, @Fetch property wrappers
- queries-crud.md - Insert, update, delete, fetch operations
- dynamic-queries.md - FetchKeyRequest, search, aggregations
- relationships-joins.md - Joins, multi-table queries
- database-setup.md - Configuration, migrations, seeding
- cloudkit-sync.md - SyncEngine, sharing, metadata
- testing.md - Test utilities and patterns
- migration-comparison.md - SwiftData comparison and migration guide
- common-issues.md - Troubleshooting and debugging