Reputation: 451
When I instantiate a model and set a relationship to a persistent object, the model is stored in the container without calling insert
on it.
Given
@Model
final class Order {
@Attribute(.unique)
var orderId: String
var items: [Item] = []
init(orderId: String) {
self.orderId = orderId
}
}
@Model
final class Item {
@Attribute(.unique)
var timestamp: Date
var order: Order?
init(timestamp: Date) {
self.timestamp = timestamp
}
}
I create a Item
let item = Item(timestamp: Date())
// here the order is not stored
item.order = sharedModelContainer.mainContext.anOrder
// here after setting the relationship to an existing order the item is stored
anOrder
is just
extension ModelContext {
var anOrder: Order? {
let desc = FetchDescriptor(predicate: #Predicate<Order> { order in true })
let orders = try! fetch(desc)
return orders.first
}
}
No insert
is called on any context.
Disabling auto-save is not a solution. My question is why it is saved without inserting it.
Is it supposed to be like that? Is it desirable?
Upvotes: 1
Views: 695
Reputation: 1557
SwiftData seems to automatically insert into context if you create a new object for which any of the parameters contains an object already in the context, or if you assign to an object a value which is that of an object already in the context.
In your example, even though you never added the item to the context, it will be automatically added because you're assigning an order that is already in the context (since you're fetching it from the context).
I suppose it makes sense because, based on your Order
model, orders have the items
property that references items and if an order is already in the context, it cannot reference an item that is not in the context.
The only way to avoid this behavior, it seems, is to create new object entirely.
So, in your example, if you were to create a new order, without inserting into the context, and then created a new item and assigned the new order to it, none will be added to the context until you specifically insert either of them.
And inserting either the new order or the new item will automatically insert both, since there's a relationship between the two.
Upvotes: 0