I am encountering an issue when attempting to share the same ModelContainer
instance between two separate targets: App
and WidgetBundle
. To achieve this, I created a StorageController
to manage the ModelContainer
and injected it into both targets.
// StorageController.swift
@MainActor
public static var globalInstance: StorageController = StorageController()
let modelContainer: ModelContainer
let modelContext: ModelContext
@MainActor
init() {
do {
let schema = Schema([
Item.self,
])
let config = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)
modelContainer = try ModelContainer(for: schema, configurations: config)
modelContext = modelContainer.mainContext
Logger().info("init modelContainer")
guard let urlApp = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).last else { return }
let url = urlApp.appendingPathComponent("default.store")
if FileManager.default.fileExists(atPath: url.path) {
Logger().info("swiftdata db at (url.absoluteString)")
} else {
Logger().warning("can't find swiftdata db")
}
} catch {
fatalError("Could not initialize ModelContainer")
}
}
// MyWidgetExtentionBundle.swift
@main
struct MyWidgetExtentionBundle: WidgetBundle {
@MainActor
init() {
Logger().info("MyWidgetExtentionBundle init")
let sc = StorageController.globalInstance
AppDependencyManager.shared.add(dependency: sc)
}
var body: some Widget {
MyWidgetExtention()
}
}
// AppIntentsInWidgetExtentionApp.swift
@main
struct AppIntentsInWidgetExtentionApp: App {
@State
private var storageController: StorageController
init() {
let sc = StorageController.globalInstance
storageController = sc
}
var body: some Scene {
WindowGroup {
VStack {
Text("Total item cnt:(storageController.fetchItems().count)")
Button("Add Item") {
storageController.addItem(name: "Item-(UUID().uuidString)")
}
}
}
}
}
However, after adding logging to verify the location of the ModelContainer
store file, I found that two different default.store
files are being created.
# start with App
swiftdata db at file:///Users/username/Library/Developer/CoreSimulator/Devices/99106351-788D-4605-A5E6-475AD73ED05C/data/Library/Application%20Support/default.store
# start with WidgetBundle
swiftdata db at file:///Users/username/Library/Developer/CoreSimulator/Devices/99106351-788D-4605-A5E6-475AD73ED05C/data/Containers/Data/Application/7465C92B-AC5A-4AB0-BA68-2EEB78C16A38/Library/Application%20Support/default.store
What is the correct approach to ensure that the ModelContainer
is shared between the App
and WidgetBundle
targets, so that data remains synchronized?
It turns out that the system treats the App and WidgetBundle as separate processes, preventing them from sharing containers. To enable container sharing across targets, follow the guide on using the App Groups feature.