Background:
I have complex Swift Data models with some Relationships, and at some point, my Xcode Preview is no longer working when I want to init a ModelContainer in it. So I tried to debug and create a simple file with no dependencies with other parts of my project.
Here's my simple code:
import Foundation
import SwiftUI
import SwiftData
struct DebugView: View {
var body: some View {
Text("Hello")
}
}
@Model
class User {
var name: String
init(name: String) {
self.name = name
}
}
#Preview {
let config = ModelConfiguration(UUID().uuidString, isStoredInMemoryOnly: true)
let container = try! ModelContainer(for: User.self, configurations: config) // This line failed
DebugView()
}
The thing is even this simple view cannot be shown in the Preview window. Error message:
enter image description here
I'm sure that the crash line is at the ModelContainer init because it works fine without it.
I tried to delete the cache data with command:
xcrun simctl --set previews delete all
But it's still not working.
The weird thing is, when I created a new project and move all the files in it, it works at the beginning. But it started to failed when I tried to do some modifications on other files (these simple codes stay unchanged).
Does any one have any idea?
-
1Pretty sure nowadays the app template shows you how to use preview traits to configure the preview model containermalhal– malhal2025年12月24日 18:15:28 +00:00Commented Dec 24 at 18:15
1 Answer 1
Preview needs to be provided data just like you would at "App" level when you start the app on Simulator or on Device.
The best way to provide mock data for preview is using PreviewModifier
Here is a sample SwiftData Modifier
struct SwiftDataPreview: PreviewModifier {
//All the Model types
static let types: [any PersistentModel.Type] = [Item.self]
//Make mock/sample context
static func makeSharedContext() async throws -> Context {
let schema = Schema(types)
//In Memory Context
let config = ModelConfiguration(isStoredInMemoryOnly: true)
let contailer = try ModelContainer(for: schema, configurations: config)
let context = ModelContext(contailer)
//Make any samples
for n in (0...10) {
let item = Item(timestamp: .now + TimeInterval(n))
context.insert(item)
}
return context
}
typealias Context = ModelContext
func body(content: Content, context: Context) -> some View {
content
.modelContext(context)
}
}
//Helper so you can access with dot notation
extension PreviewTrait where T == Preview.ViewTraits {
@MainActor static var swiftDataInMemory: Self = .modifier(SwiftDataPreview())
}
Then you can use it with
#Preview(traits: .swiftDataInMemory) {
ContentView()
}