I have a one-to-many relationship between two models:
import SwiftData
@Model
final class TrackedTask {
@Relationship(
deleteRule: .deny, // can't use .cascade with a non-optional 1:N relationship
inverse: \TaskEntry.task
)
var entries = [TaskEntry]()
}
@Model
final class TaskEntry {
@Relationship var task: TrackedTask
}
Ideally I would use deleteRule: .cascade
, but this requires me to specify task
as optional, which just seems wrong to me, since a TaskEntry
should always have an associated task. Is the canonical thing to do just accept that TaskEntry.task
has to be optional?
I was hoping to use explicit error handling like so:
// ...in a SwiftUI view...
do {
try modelContext.save()
} catch {
print("\(error)")
}
But, presumably due to multithreading shenanigans, the fatal error thrown cannot be caught in this statement and crashes the app. Is there a way of ensuring that a record that has associated records can't be deleted without crashing the app?
In practice, I will probably just remove the ability to delete tasks and just use a kind of soft delete instead. But it would be interesting to get an answer to this either way as I haven't found one anywhere online.
An optional Relationship
is actually “right” for a number of reasons starting with that it is the default for CoreData so a lot of features require it but most important
CloudKit requires all relationships to be optional
https://developer.apple.com/documentation/swiftdata/syncing-model-data-across-a-persons-devices
Which tends to be the default since syncing between devices and iCloud backup is a positive feature.
Also, this property becomes a little less relevant if you are using SwiftUI because you will want to use FetchRequest
so you can observe changes to the array