SwiftData preview sample code

Hi,

re: the SwiftData session "Create an app with SwifData" (https://developer.apple.com/videos/play/wwdc2023/10154)

I noted the mention of generating sample preview data. In CoreData, I had a similar need and this was achieved by creating a shared in-memory context; fairly straight forward.

The example given for SwiftData was decorated with @MainActor and then added to the target project, then in the #Preview closure, the modelContainer is amended to point to the preview data. Anyways, my problem is that I'm receiving an error when trying to render the preview in question:

main actor-isolated let 'previewContainer' can not be referenced from a non-isolated context

I suppose my issue is not having used the MainActor wrapper before and being unclear on what's possibly going wrong here (or if it's not just a "me" problem).

Can anyone help?

Post not yet marked as solved Up vote post of pjc83 Down vote post of pjc83
4.2k views

Replies

It seems to be a problem in the #Preview macro. In the demo app (SampleTrips), I've managed to get it working using the old style previews:

@MainActor
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .modelContainer(PreviewSampleData.container)
    }
}

Hi @pjc83, this is a known issue. There is however a workaround. Just use MainActor.assumeIsolated like so:

#Preview {
    MainActor.assumeIsolated {
        ContentView()
            .modelContainer(previewContainer)
    }
}
  • Thanks! It worked. Macbook Air M1 MacOS 13.3 Xcode 15 Beta

Add a Comment

Thanks both, the MainActor.assumeIsolated worked for me such I can still use the new #Preview macro, too.

Thanks for the help fixing the preview, however I'm hitting issues when running the app in the simulator. Maybe something isn't setup right for working with the backend? Getting these errors when trying to create a new file in the running app:

os_unix.c:46973: (0) open(/Users/myUserName/Library/Developer/CoreSimulator/Devices/17277B7F-0589-4D47-B3BF-C4C910FC23D6/data/Containers/Data/Application/C4A2EDA5-4BD0-4D9C-8437-75DFEC2B269F/Library/Application Support/default.store) - Undefined error: 0
API call with unopened database connection pointer
misuse at line 179760 of [554764a6e7]
  • I'm facing the same problem as well.

Add a Comment

on Xcode15 beta4, all workarounds above don’t work for me.

I notice that release notes mentioned that it is a known issue and recommend to run on device replacing preview, but it is not convenient.

is there any other workaround?

I found some working solutions. This is how I generate the preview containter:

let previewContainer: ModelContainer = {
    do {
        let container = try ModelContainer(for: Snippet.self,
                                           configurations: ModelConfiguration(isStoredInMemoryOnly: true))
        
        Task { @MainActor in
            
            let context = container.mainContext
            
            let snip = Snippet.example2()

            
            let folder = Folder(name: "folder with favorite snippet")
            context.insert(folder)
            folder.snippets.append(Snippet(isFavorite: true, 
                     title: "favorite snippet"))

            // add test data here
        }
        
        return container
    } catch {
        fatalError("Failed to create container: \(error.localizedDescription)")
    }
}()

#Preview {
     FolderListView()
        .modelContainer(previewContainer)
}

Using view where I need to pass in a SwiftData object is more complex. I created a demo project with more examples. All previews are working for Xcode 15 https://github.com/gahntpo/SnippetBox-SwiftData