GO FURTHER, FASTER: Try the Swift Career Accelerator today! >>

SOLVED: Preview crashes when trying to display SwiftData model

Forums > SwiftUI

I'm trying to build a view for my app and preview keep crashing when trying to load the SwiftData model in the preview. The app works perfectly fine in the simulator and on my iPhone. What am I doing wrong and how do I fix this?

This is the view that keep crashing

import SwiftData
import SwiftUI

struct EditConsumedDrinkView: View {
  @Environment(\.modelContext) var modelContext

  @Bindable var consumedDrink: ConsumedDrink

  var body: some View {
    Text(consumedDrink.drink.name)
      .navigationTitle("Consumed Drink")
      .navigationBarTitleDisplayMode(.inline)
  }
}

#Preview {
  let config = ModelConfiguration(isStoredInMemoryOnly: true)
  let container = try! ModelContainer(for: ConsumedDrink.self, configurations: config)

  let drink = Drink(name: "Water", amount: 16.9, unitOfMeasure: .ounce, image: "water")
  let consumed = ConsumedDrink(drink: drink)

  return EditConsumedDrinkView(consumedDrink: consumed)
    .modelContainer(container)
}

The ConsumedDrink class

import SwiftData

@Model
class ConsumedDrink {

  let id: UUID
  let drink: Drink
  var date: Date

  init(drink: Drink, date: Date = Date()) {
    self.id = UUID()
    self.drink = drink
    self.date = date
  }
}

The Drink class

import SwiftData

@Model
class Drink {
  let id: UUID = UUID()
  var name: String = ""
  var shortName: String = ""
  var amount: Double = 0.0
  var unitOfMeasure: FluidUnit = FluidUnit.ounce
  let date: Date = Date()
  var image: String = "water"
  var favorite: Bool = false
  var isHidden: Bool = false

  init(name: String, amount: Double, unitOfMeasure: FluidUnit, image: String, favorite: Bool = false, shortName: String = "", isHidden: Bool = false) {
    self.id = UUID()
    self.name = name
    self.amount = amount
    self.unitOfMeasure = unitOfMeasure
    self.date = Date()
    self.image = image
    self.favorite = favorite
    self.shortName = shortName
    self.isHidden = isHidden
  }

}

   

I figured it out. I had to rewrite the preview

#Preview {
  do {
    let container = try ModelContainer(for: ConsumedDrink.self, Drink.self, configurations: ModelConfiguration(isStoredInMemoryOnly: true))

    let drink = Drink(name: "Water", amount: 116.9, unitOfMeasure: .ounce, image: "water")
    container.mainContext.insert(drink)

    let consumed = ConsumedDrink(drink: drink)

    container.mainContext.insert(consumed)

    return EditConsumedDrinkView(consumedDrink: consumed)
      .modelContainer(container)
  } catch {
    return Text("error \(error.localizedDescription)")
  }
}

   

I lost 3/4 of a day to this problem. Thank you @syclonefx for posting the solution.

   

At WWDC24 Apple added some capabilities here to do this much more easily using Preview traits.

https://developer.apple.com/videos/play/wwdc2024/10137/?time=418

#Preview(traits: .sampleData) {
    @Previewable @Query var trips: [Trip]
    BucketListItemView(trip: trips.first)
}

I've found this makes all of my previews now work with my SwiftData models, whereas before it was pretty messy and often-times wouldn't work as I expected, especially where there is a relationship.

   

Hacking with Swift is sponsored by try! Swift Tokyo.

SPONSORED Ready to dive into the world of Swift? try! Swift Tokyo is the premier iOS developer conference will be happened in April 9th-11th, where you can learn from industry experts, connect with fellow developers, and explore the latest in Swift and iOS development. Don’t miss out on this opportunity to level up your skills and be part of the Swift community!

Get your ticket here

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.