Search code examples
iosswiftxcodeswiftuiswiftdata

SwiftUI Preview crashes when making calls to SwiftData related methods?


I have a Button in my View which calls an action which either increments or deletes data from a SwiftData model.

On my mobile device and the simulators, the app works perfectly. However, in the SwiftUI preview that is generated clicking on any button causes the preview to crash and dump logs.

This is all running in the latest Xcode build 15.2

Button SwiftUI code:

Button("🍺", action: { 
   self.recordDrink(drink:"beer")
}).buttonStyle(LiquorButtonStyle())

recordDrink()

private func recordDrink(drink: String) {
    let dm = DrinkModel(drink: drink, date: Date())
    modelContext.insert(dm)
}

The model being used:

import SwiftData
import Foundation

@Model

class DrinkModel {
    var drink: String
    var date: Date
    
    init(drink: String, date: Date) {
        self.drink = drink
        self.date = date
    }
}

The crash generates the following logs:

Exception Type:  EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x000000010663a938
Termination Reason: SIGNAL 5 Trace/BPT trap: 5
Terminating Process: exc handler [8725]

Triggered by Thread:  0

Thread 0 Crashed::  Dispatch queue: com.apple.main-thread
0   libswiftCore.dylib                     0x10663a938 _assertionFailure(_:_:file:line:flags:) + 248
1   SwiftData                              0x10533892c 0x105324000 + 84268
2   SwiftData                              0x1053a585c 0x105324000 + 530524
3   SwiftData                              0x1053a94dc 0x105324000 + 546012
4   SwiftData                              0x105368c30 0x105324000 + 281648
5   DrinkLess                              0x1043bfd68 DrinkModel.init(drink:date:) + 376 (@__swiftmacro_9DrinkLess0A5Model0C0fMm_.swift:2)
6   DrinkLess                              0x1043bfbe0 DrinkModel.__allocating_init(drink:date:) + 72
7   DrinkLess                              0x1043c5a6c CalculatorView.recordDrink(drink:) + 304 (CalculatorView.swift:74)
8   DrinkLess                              0x1043c5924 closure #1 in closure #1 in closure #1 in closure #1 in closure #1 in CalculatorView.body.getter + 68 (CalculatorView.swift:44)

The logs don't contain much information beyond line 8 talking about closures.

My guess is either the SwiftUI preview can't seem to parse the Model and the reads and writes to it, or something about putting the function in a closure is causing problems, or a closure somewhere down the line.

To reiterate, the app works fine on a physical device. How do I fix the SwiftUI Preview environment?


Solution

  • You have to give Swift some sort of container but here’s a great HackinWithSwift tutorial explaining it. https://www.hackingwithswift.com/quick-start/swiftdata/how-to-use-swiftdata-in-swiftui-previews

    #Preview {
        let config = ModelConfiguration(isStoredInMemoryOnly: true)
        let container = try! ModelContainer(for: DrinkModel.self, configurations: config)
    
        let drink = DrinkModel(drink: "Coca Cola", date: .now)
        return ContentView(drink: drink)
            .modelContainer(container)
    }
    

    Personally I would replace the Date() by a simple string because that makes handling easier.