NnSwiftDataKit is a lightweight Swift package that streamlines the setup of SwiftData containers in apps that use App Groups. It provides:
- a clean way to create a
ModelConfigurationthat stores data inside an App Group - automatic access to the correct
UserDefaultssuite - a one-liner to build a
ModelContainerandUserDefaultstogether - a convenient
Sceneextension for initializing aModelContainer - optional database path printing for debugging via a
ModelContainerhelper
The package does not define any SwiftData models and does not manage schema or migrations. Your app remains fully in control of its domain and data types.
- Builds a
ModelConfigurationusing an App Group identifier. - Returns the correct
UserDefaultssuite for the same App Group. - Provides a
Scene.initializeSwiftDataModelContainerhelper to inject containers cleanly. - Migrates existing SwiftData stores between App Groups with optional automatic cleanup.
- Supports custom schemas and migration plans.
- Works with iOS and macOS targets.
Add the package to your Package.swift file:
.package(url: "https://github.com/nikolainobadi/NnSwiftDataKit", from: "0.9.0")import NnSwiftDataKitmakeAppGroupConfiguration(appGroupId:fileManager:)→ModelConfiguration+UserDefaultsmakeAppGroupModelContainer(schema:appGroupId:fileManager:migrationPlan:)→ModelContainer+UserDefaultsmigrateAppGroupSwiftDataStoreIfNeeded(from:to:fileManager:deleteOldAfterMigration:)→ migrates database between App GroupsScene.initializeSwiftDataModelContainer(schema:migrationPlan:configuration:printDatabasePath:)→ attaches a configured container to a sceneModelContainer.printStoreFilePath()→ logs the resolved store location
Use makeAppGroupConfiguration to prepare a ModelConfiguration and the App Group UserDefaults instance (throws SwiftDataContextError.noAppGroupAccess if the group is unavailable):
do {
let (config, defaults) = try makeAppGroupConfiguration(
appGroupId: "group.com.example.app"
)
print("App Group UserDefaults:", defaults)
} catch {
print("Failed to configure SwiftData container:", error)
}Build a ready-to-use ModelContainer and UserDefaults in one step. You can pass a migration plan when needed:
let (container, defaults) = try makeAppGroupModelContainer(
schema: Schema([MyModel.self]),
appGroupId: "group.com.example.app",
migrationPlan: MyMigrationPlan.self
)
container.printStoreFilePath() // optional: logs the store locationIf you need to change your App Group identifier, use migrateAppGroupSwiftDataStoreIfNeeded to safely migrate your existing database. This must be called before creating the ModelContainer:
do {
// Migrate from old App Group to new App Group
try migrateAppGroupSwiftDataStoreIfNeeded(
from: "group.com.example.oldapp",
to: "group.com.example.newapp",
deleteOldAfterMigration: true // automatically removes old database after successful migration
)
// Now create the container with the new App Group
let (container, defaults) = try makeAppGroupModelContainer(
schema: Schema([MyModel.self]),
appGroupId: "group.com.example.newapp"
)
} catch {
print("Migration or container setup failed:", error)
}The migration function:
- Checks if the new App Group container exists
- If not, but the old container exists, copies all SwiftData files to the new location
- Optionally deletes the old container after successful migration (set
deleteOldAfterMigration: falseto keep it) - Is safe to call repeatedly (no-op if migration is already complete)
Use the initializeSwiftDataModelContainer modifier inside your Scene builder:
@main
struct ExampleApp: App {
var body: some Scene {
let (config, _) = try! makeAppGroupConfiguration(
appGroupId: "group.com.example.app"
)
WindowGroup {
ContentView()
}
.initializeSwiftDataModelContainer(
schema: Schema([MyModel.self]),
migrationPlan: MyMigrationPlan.self,
configuration: config,
printDatabasePath: true
)
}
}This initializes a SwiftData container using your App Group and applies it to the scene.
If the App Group container or the associated UserDefaults suite cannot be accessed, the helpers throw:
SwiftDataContextError.noAppGroupAccessAny feedback or ideas to enhance NnSwiftDataKit would be well received. Please feel free to open an issue if you'd like to help improve this Swift package.
NnSwiftDataKit is licensed under the MIT License. See the LICENSE file for details.