- Notifications
You must be signed in to change notification settings - Fork55
A fast, lightweight replacement for SwiftData, powered by SQL and supporting CloudKit synchronization.
License
pointfreeco/sqlite-data
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
Afast, lightweight replacement for SwiftData, powered by SQL and supportingCloudKit synchronization.
- Learn more
- Overview
- Quick start
- Performance
- SQLite knowledge required
- Overview
- Demos
- Documentation
- Installation
- Community
- License
This library was motivated and designed over the course of many episodes onPoint-Free, a video series exploring advanced programming topics in theSwift language, hosted byBrandon Williams andStephen Celis. To support the continued development of thislibrary,subscribe today.

SQLiteData is afast, lightweight replacement for SwiftData, including CloudKitsynchronization (and even CloudKit sharing), built on top of the popularGRDB library.To populate data from the database you can use@Table and@FetchAll, which aresimilar to SwiftData's@Model and@Query:
| SQLiteData | SwiftData |
|---|---|
@FetchAllvaritems:[Item]@TablestructItem{letid:UUIDvartitle=""varisInStock=truevarnotes=""} | @Queryvaritems:[Item]@ModelclassItem{vartitle:StringvarisInStock:Boolvarnotes:Stringinit( title:String="", isInStock:Bool=true, notes:String=""){self.title= titleself.isInStock= isInStockself.notes= notes}} |
Both of the above examples fetch items from an external data store using Swift data types, and bothare automatically observed by SwiftUI so that views are recomputed when the external data changes,but SQLiteData is powered directly by SQLite and is usable from UIKit,@Observable models, andmore.
For more information on SQLiteData's querying capabilities, seeFetching model data.
Before SQLiteData's property wrappers can fetch data from SQLite, you need to provide–atruntime–the default database it should use. This is typically done as early as possible in yourapp's lifetime, like the app entry point in SwiftUI, and is analogous to configuring model storagein SwiftData:
| SQLiteData | SwiftData |
|---|---|
@mainstructMyApp:App{init(){prepareDependencies{letdb=try!DatabaseQueue( // Create/migrate a database // connection) $0.defaultDatabase= db}} // ...} | @mainstructMyApp:App{letcontainer={ // Create/configure a containertry!ModelContainer(/* ... */)}()varbody:someScene{WindowGroup{ContentView().modelContainer(container)}}} |
Note
For more information on preparing a SQLite database, seePreparing a SQLite database.
ThisdefaultDatabase connection is used implicitly by SQLiteData's strategies, like@FetchAll and@FetchOne, which are similar to SwiftData's@Query macro, but more powerful:
| SQLiteData | SwiftData |
|---|---|
@FetchAllvaritems:[Item]@FetchAll(Item.order(by: \.title))varitems@FetchAll(Item.where(\.isInStock))varitems@FetchAll(Item.order(by: \.isInStock))varitems@FetchOne(Item.count())varitemsCount=0 | @Queryvaritems:[Item]@Query(sort:[SortDescriptor(\.title)])varitems:[Item]@Query(filter: #Predicate<Item>{ $0.isInStock})varitems:[Item]// No @Query equivalent of ordering// by boolean column.// No @Query equivalent of counting// entries in database without loading// all entries. |
And you can access this database throughout your application in a way similar to how one accessesa model context, via a property wrapper:
| SQLiteData | SwiftData |
|---|---|
@Dependency(\.defaultDatabase)vardatabaseletnewItem=Item(/* ... */)try database.write{ dbintryItem.insert{ newItem}.execute(db))} | @Environment(\.modelContext)varmodelContextletnewItem=Item(/* ... */)modelContext.insert(newItem)try modelContext.save() |
Note
For more information on how SQLiteData compares to SwiftData, seeComparison with SwiftData.
Further, if you want to synchronize the local database to CloudKit so that it is available onall your user's devices, simply configure aSyncEngine in the entry point of the app:
@mainstructMyApp:App{init(){prepareDependencies{ $0.defaultDatabase=try!appDatabase() $0.defaultSyncEngine=SyncEngine( for: $0.defaultDatabase, tables:Item.self)}} // ...}
Note
For more information on synchronizing the database to CloudKit and sharing records with iCloudusers, seeCloudKit Synchronization.
This is all you need to know to get started with SQLiteData, but there's much more to learn. Readthearticles below to learn how to best utilize this library:
- Fetching model data
- Observing changes to model data
- Preparing a SQLite database
- Dynamic queries
- CloudKit Synchronization
- Comparison with SwiftData
SQLiteData leverages high-performance decoding fromStructuredQueries to turn fetched data intoyour Swift domain types, and has a performance profile similar to invoking SQLite's C APIs directly.
See the following benchmarks againstLighter's performance test suite for ataste of how it compares:
Orders.fetchAll setup rampup duration SQLite (generated by Enlighter 1.4.10) 0 0.144 7.183 Lighter (1.4.10) 0 0.164 8.059┌──────────────────────────────────────────────────────────────────┐│ SQLiteData (1.0.0) 0 0.172 8.511 │└──────────────────────────────────────────────────────────────────┘ GRDB (7.4.1, manual decoding) 0 0.376 18.819 SQLite.swift (0.15.3, manual decoding) 0 0.564 27.994 SQLite.swift (0.15.3, Codable) 0 0.863 43.261 GRDB (7.4.1, Codable) 0.002 1.07 53.326SQLite is one of themost established and widely distributed pieces ofsoftware in the history of software. Knowledge of SQLite is a great skill for any app developer tohave, and this library does not want to conceal it from you. So, we feel that to best wield thislibrary you should be familiar with the basics of SQLite, including schema design and normalization,SQL queries, including joins and aggregates, and performance, including indices.
With some basic knowledge you can apply this library to your database schema in order to queryfor data and keep your views up-to-date when data in the database changes, and you can useStructuredQueries to build queries, either using its type-safe, discoverablequery building APIs, or using its#sql macro for writingsafe SQL strings.
Further, this library is built on the popular and battle-testedGRDB library forinteracting with SQLite, such as executing queries and observing the database for changes.
This repo comes withlots of examples to demonstrate how to solve common and complex problems withSQLiteData. Check outthis directory to see them all, including:
Case Studies
Demonstrates how to solve some common application problems in an isolated environment, inboth 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 toshare records with other iCloud users. See our dedicated articles onCloudKit SynchronizationandCloudKit Sharing for more information.Reminders
A rebuild of Apple'sReminders app that uses a SQLite database tomodel the reminders, lists and tags. It features many advanced queries, such as searching, statsaggregation, and multi-table joins. It also features CloudKit synchronization and sharing.SyncUps
This application is a faithful reconstruction of one of Apple's more interesting sampleprojects, calledScrumdinger, and uses SQLite to persist the data for meetings.We have also added CloudKit synchronization so that all changes are automatically made availableon all of the user's devices.
The documentation for releases andmain are available here:
You can add SQLiteData to an Xcode project by adding it to your project as a package…
…and adding theSQLiteData product to your target.
If you want to use SQLiteData in aSwiftPM project, it's assimple as adding it to yourPackage.swift:
dependencies:[.package(url:"https://github.com/pointfreeco/sqlite-data", from:"1.0.0")]
And then adding the following product to any target that needs access to the library:
.product(name:"SQLiteData",package:"sqlite-data"),
If you want to discuss this library or have a question about how to use it to solve a particularproblem, there are a number of places you can discuss with fellowPoint-Free enthusiasts:
For long-form discussions, we recommend thediscussions tab of this repo.
For casual chat, we recommend thePoint-Free Community Slack.
This library is released under the MIT license. SeeLICENSE for details.
About
A fast, lightweight replacement for SwiftData, powered by SQL and supporting CloudKit synchronization.
Topics
Resources
License
Code of conduct
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Uh oh!
There was an error while loading.Please reload this page.