I have an Order model that contains Items
@Model
class Order: Decodable {
@Attribute(.unique) var orderId: String
var items: [Item]
}
When inside the list view, I fetch all the orders, the Items are not loaded and shows empty
var body: some View {
List {
DynamicQuery(orderDescriptor) { orders in
ForEach(orders) { order in
ForEach(order.items) { item in
if let sandwichName = item.data?.sandwichName {
Text(sandwichName)
}
}
}
}
.onReceive(toolbarModel.$selectedDate) { newDate in
print("Date changed to: \(newDate)")
getOrders(ofDate: newDate) { result in
switch result {
case .success:
print("Order Fetch successful for Date \(newDate)")
case .failure(let error):
print("Order Fetch failed with \(error)")
}
}
}
}
This is how I am inserting the orders into modelcontext
let orders = try JSONDecoder().decode([Order].self, from: jsonData)
for order in orders {
// print(order.items) // crashes the app
modelContext.insert(order)
}
I tried defining the relationshipKeyPathsForPrefetching but doesnt work.
private var orderDescriptor: FetchDescriptor<Order> {
var fetchDescriptor = FetchDescriptor(
predicate: Order.currentOrders(with: toolbarModel.selectedDate),
sortBy: [SortDescriptor(\Order.time)]
)
// fetchDescriptor.relationshipKeyPathsForPrefetching = [\.items]
return fetchDescriptor
}
I know the relationship are lazy load but I assume if I am referring the items inside the list, it should load? If I reload the app and wait a bit, I could see some items so seems like its loading but not right away. Anything that I am missing?
Turns out, the inverse relationship was causing the issue. Previously, I had the relationship between Order and Item defined as
@Model
class Order: Decodable {
@Attribute(.unique) var orderId: String
var items: [Item]
}
@Model
class Item: Decodable {
@Attribute(.unique) var orderItemId: String
@Relationship(inverse: \Order.items) var order: Order?
}
Changed that to
@Model
class Order: Decodable {
@Attribute(.unique) var orderId: String
@Relationship(inverse: \Item.order) var items = [Item]()
}
@Model
class Item: Decodable {
@Attribute(.unique) var orderItemId: String
var order: Order?
}
and it worked.