One way to do this is to have a property in the model that stores the relative order index.
Start by adding this property to the model class:
var orderIndex: Int
This will need to be added to the initialiser as well.
When querying for a list of items, you can sort by this property:
@Query(sort: \ChecklistItem.orderIndex) private var items: [ChecklistItem]
For the view's move action you can do this:
.onMove { source, destination in
// Make a copy of the current list of items
var updatedItems = items
// Apply the move operation to the items
updatedItems.move(fromOffsets: source, toOffset: destination)
// Update each item's relative index order based on the new items
// Can extract and reuse this part if the order of the items is changed elsewhere (like when deleting items)
// The iteration could be done in reverse to reduce changes to the indices but isn't necessary
for (index, item) in updatedItems.enumerated() {
item.orderIndex = index
}
}
That last part I would put in an extension like so:
extension [ChecklistItem] {
func updateOrderIndices() {
for (index, item) in enumerated() {
item.orderIndex = index
}
}
}
and you can instead write this for better ease of use and reusability:
items.updateOrderIndices() // run after changes to the order of `items`
When you add a new item, you will need to provide a value for its orderIndex property. This would be resolved as the number of current items (as indexing starts at 0). So if there are 5 items (with indices 0, 1, 2, 3, 4), the new index would be 5.
Here's an example of how to do that:
// Fetch the number of all items that contribute to the relative index ordering
let descriptor = FetchDescriptor<ChecklistItem>(/* add filtering or sorting if needed */)
let count = (try? modelContext.fetchCount(descriptor)) ?? 0
// Pass the next index to the new item
let newItem = ChecklistItem(..., orderIndex: count)
modelContext.insert(newItem)
This is only a basic solution and probably isn't the most optimised as any change, even to a single item, results in all the items being updated.
Hope it helps anyway!