My problem is that I have two Models in my app – Car
and Refuel
. First one is to contain just a name of a car. User can have few cars. When a user refuels a tank and wants to log it, he selects a car from those previously saved and fills out the rest of the data. The issue that I’m having, is that my app crashes when I try to save a model (probably because I’m setting the relationship wrong).
First error I’m getting when selecting a Car from a picker is:
Picker: the selection "RefuelApp.Car" is invalid and does not have an associated tag, this will give undefined results.
The second one is when I’m closing the sheet (when the data should be saved):
//In Refuel.swift
@Relationship var car: Car
{
@storageRestrictions(accesses: _$backingData, initializes: _car)
init(initialValue) {
_$backingData.setValue(forKey: .car, to: initialValue)
_car = _SwiftDataNoType()
}
get {
_$observationRegistrar.access(self, keyPath: .car)
return self.getValue(forKey: .car)
}
set {
_$observationRegistrar.withMutation(of: self, keyPath: .car) {
self.setValue(forKey: .car, to: newValue) // <----- Thread 1: EXC_BREAKPOINT (code=1, subcode=0x1cc1641e0)
}
}
}
Here is some sample code:
RefuelEditView.swift
import SwiftUI
import SwiftData
struct RefuelEditView: View {
@Environment(.dismiss) private var dismiss
@Environment(.modelContext) private var modelContext
@Query private var cars: [Car]
@Bindable var refill: Refuel
let isNew: Bool
@State private var selectedCar: Car
init(refill: Refuel, car: Car = Car(), isNew: Bool = false) {
self.refill = refill
self.isNew = isNew
self.selectedCar = car
}
var body: some View {
Form {
Section(header: Text("Car")) {
Picker(selection: $selectedCar, label: Text("Car")) {
Text("--None--").tag(nil as Car?)
ForEach(cars) { car in
Text(car.name).tag(car) // <----- Do not know if this is a correct way to populate a picker
}
}
}
Section(header: Text("Refuel details")) {
DatePicker(selection: .init(projectedValue: $refill.timestamp), label: { Text("Date") })
HStack{
LabeledContent("Odometer") {
TextField("km", value: $refill.odo, format: .number.grouping(.automatic))
.keyboardType(.decimalPad)
}
}
}
}
.navigationTitle(isNew ? "New Refuel" : "Refuel")
.toolbar {
if isNew {
ToolbarItem(placement: .confirmationAction) {
Button("Done") {
let item = refill
item.car = selectedCar // <----- I guess this is where I try to save it in a wrong way
modelContext.insert(item)
dismiss()
}
}
ToolbarItem(placement: .cancellationAction) {
Button("Cancel") {
modelContext.delete(refill)
dismiss()
}
}
}
}
}
}
Car.swift
import Foundation
import SwiftData
@Model
final class Car: Identifiable {
let id = UUID()
var name: String
@Relationship(deleteRule: .cascade, inverse: Refuel.car) var refuels: [Refuel]?
init() {
self.name = ""
}
init(name: String) {
self.name = name
}
}
Refulel.swift
import Foundation
import SwiftData
@Model
final class Refuel: Identifiable {
let id = UUID()
@Relationship var car: Car
var timestamp: Date
private var odo_backend: Double = 0
init(car: Car) {
self.car = car
self.odo_backend = 0
self.timestamp = .now
}
init(car: Car, timestamp: Date, odo: Double) {
self.car = car
self.odo_backend = odo
self.timestamp = timestamp
}
}