OpenSwiftData is an open-source, cross-platform implementation of SwiftData’s persistence APIs that lets SwiftData apps build with xtool on Linux, where Apple’s SwiftData framework is unavailable. It uses GRDB and SQLite for storage.
OpenSwiftData is under active development. See Compatibility for behavior that differs from Apple’s SwiftData implementation.
- Swift 6.0 or later
- iOS 17, macOS 14, tvOS 17, or watchOS 10
- Xcode or xtool to build Apple platform apps
Add the package dependency and products to your app target in Package.swift:
.package(url: "https://github.com/ChakornK/OpenSwiftData", branch: "main").product(name: "OpenSwiftData", package: "OpenSwiftData"),
.product(name: "OpenSwiftDataSQLite", package: "OpenSwiftData"),Create a model and a file-backed store. Insert a note, save it, then fetch it:
import Foundation
import OpenSwiftData
import OpenSwiftDataSQLite
@Model
final class Note {
var text: String
init(text: String) {
self.text = text
}
}
let storeURL = URL.applicationSupportDirectory
.appending(path: "Notes.sqlite")
let configuration = ModelConfiguration.sqliteFile("notes", url: storeURL)
let container = try ModelContainer(
for: Note.self,
configurations: configuration
)
let context = container.mainContext
context.insert(Note(text: "First note"))
try context.save()
let notes = try context.fetch(FetchDescriptor<Note>())For temporary data, replace the file configuration with:
let configuration = ModelConfiguration.sqliteMemory("notes")When you build an iOS app from Linux, Swift's #Predicate macro may refer to FoundationEssentials types that Apple's SDK normally exposes through Foundation. Add the FoundationEssentials shim package to your app's Package.swift, then add its FoundationEssentials product to the iOS app target:
.package(url: "https://github.com/ChakornK/FoundationEssentialsShim", branch: "main").product(name: "FoundationEssentials", package: "FoundationEssentialsShim"),Import FoundationEssentials in files that need its declarations. The shim re-exports Foundation:
import FoundationEssentialsFor builds on macOS, use Apple's Foundation directly.
OpenSwiftData uses its own SQLite store and cannot open Apple's SwiftData stores. It implements selected SwiftData APIs and behaviors. The source and tests show the supported surface.
The parity suite tracks behavior and API differences. Expand the list for details:
Show all
- Fetch descriptor defaults,
fetchOffsetAbsent: Apple's offset is present; OpenSwiftData's is absent. - Erase,
lastCompletedStep: Apple's probe checkpoints step 2 before its post-erase save traps; OpenSwiftData completes step 4. - Erase,
pendingFetchReturned: the Apple probe does not complete the fetch after its save trap; OpenSwiftData completes it. - Erase,
pendingNamesAfterSave: the Apple probe has no fetched names after its save trap; OpenSwiftData fetches[\"pending\"]. - Erase,
pendingSaveReturned: the Apple probe does not complete the save aftererase(); OpenSwiftData completes it. - Saved optional
flatMap,nick.empty.false: OpenSwiftData matchesdélta; Apple returns no matches. - Saved optional
flatMap,nick.isEmpty.direct: OpenSwiftData matchesdélta; Apple returns no matches. - Saved
String.count,length.4: OpenSwiftData matchesbeta; Apple returns no matches. - Saved
String.count,length.5: OpenSwiftData matchesAlpha,Gamma, anddélta; Apple returns no matches. - Saved
String.count,length.gt5: OpenSwiftData matchesÉpsilon; Apple matches every row. - Duplicate inserts in one save,
survivorsObserved: OpenSwiftData deterministically keeps the last insert as the survivor; Apple's survivor is non-deterministic (Set iteration order), so either insert may win.
- Stores that do not conform to
DataStoreBatchingrejectdelete(model:where:includeSubclasses:). - History reported by custom stores lives in an in-memory ledger and is not durable across launches.
HistoryProviding(fetching history from the store object itself) is not implemented; useModelContext.fetchHistory(_:).- CloudKit-backed configurations reject custom stores.
- SQLite through GRDB is the default backend. CloudKit is unsupported.
- The package builds on Linux and Apple platforms. On Linux,
NotificationCenterobservers filtered withobject: contextdo not receive save notifications.