Error: This store went missing? Optional(SwiftData.PersistentIdentifier(id: SwiftData.PersistentIdentifier.ID...
The error is usually caused by how the modelContainer is initialized, and most of the time, it happens while Xcode renders the preview.
This means SwiftData can't find the model using the model's identifier.
Consider we have a preview like the one below:
#Preview {
let modelContainer = try! ModelContainer.previewContainer()
SomeView().modelContainer(modelContainer)
}
And the previewContainer
function is defined as below:
extension ModelContainer {
static func previewContainer() {
let config = ModelConfiguration(isStoredInMemoryOnly: true)
let container = try? ModelContainer(for: [Record.self], configurations: config)
// insert some sample data for preview
Task { @MainActor in
let context = container?.mainContext
context.insert(Record())
}
return container
}
}
If you turn on the Xcode preview, it works, but after a few seconds, it crashes and shows the above error.
It is typically because the preview is refreshed after your source code changes and the previewContainer is run again.
Each time it runs, the previous context and models are destroyed, but the swiftUI preview still holds a reference to that old model.
The inconsistency causes the error: the old model's id can't be found in the new context, and the new context does not have a model whose id is identical to the old model's id.
Note, by saying id
, we're talking about the PersistentIdentifier
of the model generated by SwiftData, not a custom property set by us. Even if we set a property called id
in the model, it does not affect the PersistentIdentifier
of the model.
So how to resolve the problem? Since the reason is every update of the preview will call the try! ModelContainer.previewContainer()
function, and returns a new container, we can simply make the container a static property that will not be changed during the lifetime of the app.
extension ModelContainer{
static let previewContainer: ModelContainer? = {
let config = ModelConfiguration(isStoredInMemoryOnly: true)
let container = try? ModelContainer(for: [Record.self], configurations: config)
Task { @MainActor in
let context = container?.mainContext
context.insert(Record())
}
return container
}()
}
#Preview {
SomeView().modelContainer(ModelContainer.previewContainer!)
}
In this way, the previewContainer will be called only once when the app starts, avoiding consistency between preview refreshes, and the error does not appear anymore.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。