SwiftUI SwiftData Previews not working as expected

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

I corrected the @MainActor issue, but it seems to only work with the main ContentView and not other views.

I get the following error for TripListItem for example :

failed to find a currently active container for Trip

Accepted Reply

I was still running into this and similar errors getting SwiftUI views with SwiftData to preview successfully. It seems to me that you need to instantiate the container before you can reference the SwiftData objects in the container. I was finally able to solve it with the following:

#Preview {
    MainActor.assumeIsolated {
        let container = PreviewSampleData.container
        
        return List {
            TripListItem(trip: Trip.preview)
                .modelContainer(container)
        }
    }
}
  • This fixes the MainActor issue for me, but I still get "Trip has no member 'preview'." Did you have to do something else to get that part to work? This is in beta 2.

  • Interesting! It seems like something with class extensions on SwiftData models is broken in Beta 2. I moved the preview var out of the extension and into the main class declaration for both Trip and BucketListItem and this appears to fix the issue for me.

  • Thank you, that did it! I should have thought about that.

Add a Comment

Replies

Looks like an @Model must be inserted into the context before use in SwiftUI

actor PreviewSampleData {
    @MainActor
    static var container: ModelContainer = {
        let schema = Schema([Trip.self, BucketListItem.self, LivingAccommodation.self])
        let configuration = ModelConfiguration(inMemory: true)
        let container = try! ModelContainer(for: schema, configurations: [configuration])
        let sampleData: [any PersistentModel] = [
            Trip.preview, BucketListItem.preview, LivingAccommodation.preview
        ]
        sampleData.forEach {
            container.mainContext.insert($0)
        }
        return container
    }()

    @MainActor
    static var previewTrip: Trip = {

        let container = PreviewSampleData.container
        let trip = Trip.preview
        container.mainContext.insert(trip)

        return trip
    }()
}
#Preview {
    MainActor.assumeIsolated {
        List {
            TripListItem(trip: PreviewSampleData.previewTrip)
        }
        .modelContainer(PreviewSampleData.container)
    }
}

I was still running into this and similar errors getting SwiftUI views with SwiftData to preview successfully. It seems to me that you need to instantiate the container before you can reference the SwiftData objects in the container. I was finally able to solve it with the following:

#Preview {
    MainActor.assumeIsolated {
        let container = PreviewSampleData.container
        
        return List {
            TripListItem(trip: Trip.preview)
                .modelContainer(container)
        }
    }
}
  • This fixes the MainActor issue for me, but I still get "Trip has no member 'preview'." Did you have to do something else to get that part to work? This is in beta 2.

  • Interesting! It seems like something with class extensions on SwiftData models is broken in Beta 2. I moved the preview var out of the extension and into the main class declaration for both Trip and BucketListItem and this appears to fix the issue for me.

  • Thank you, that did it! I should have thought about that.

Add a Comment

Interesting! not sure why I didn't try this 🙃

Hello, im still having this issue at Xcode beta 5, and none of the above workarounds does work either.

My #Preview Code:

#Preview {
    MainActor.assumeIsolated {
        let modelContainer: ModelContainer = ModelContainer.preview()
        return TaskListView()
            .modelContainer(modelContainer)
    }
}

My ModelContainer.preview() Code:

#if DEBUG
@MainActor
extension ModelContainer {
    static func preview() -> ModelContainer {
        do {
            let modelContainer = try ModelContainer(for: [TaskListModel.self], ModelConfiguration(inMemory: true))
            for element in [TaskListModel].preview() {
                modelContainer.mainContext.insert(element)
            }
            return modelContainer
        } catch let error {
            fatalError("[ModelContainer] static preview(taskLists:): \(error.localizedDescription)")
        }
    }
}
#endif
  • Still the case in Beta 6. I also would like to mention, that this is the case for every View (including ContentView), in contrast to @mrhanlon situation. Another thing note mentioning is that using the previewData as the modelContainer for the app (running on my iPhone) just works fine. However replacing the new Preview macro with the old preview code does not resolve the issue. So the issue must be Preview related, independent from the new macro.

  • @lucaszischka Works for me in beta 5. I use as reference the code here "https://developer.apple.com/videos/play/wwdc2023/10154/?time=564" (min 9:05), without the problem of main actor. So, I define MainActor PreviewContainer (like video) and in #Preview I have only ".modelContainer(previewContainer)" under View and use the solution of this topic for pass a preview static Item

  • Yes @Luccif I might be on the wrong thread here; im actually not using the code from the "Create an app with SwiftData" session. In this code the same error message appeared, therefore I posted my (custom) Code here. If this will not resolve itself, I will probably open an own issue.

Add a Comment