I have a simple test app with a behavior I just don't understand.
import SwiftUI
import SwiftData
struct ContentView: View {
@Environment(\.modelContext) private var modelContext
@Query private var items: [Item]
var body: some View {
NavigationView {
List {
// ForEach(items) { item in
ForEach(items.sorted(by: { $0.sortNr < $1.sortNr })) { item in
HStack{
Text("\(item.sortNr)")
Text("\(item.itemName)")
}
}
.onDelete(perform: deleteItems)
}
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
EditButton()
}
ToolbarItem {
Button(action: addItem) {
Label("Add Item", systemImage: "plus")
}
}
}
}
}
private func addItem() {
withAnimation {
let newItem1 = Item(itemName: "one", sortNr: 1)
let newItem2 = Item(itemName: "two", sortNr: 2)
let newItem3 = Item(itemName: "three", sortNr: 3)
let newItem4 = Item(itemName: "four", sortNr: 4)
modelContext.insert(newItem1)
modelContext.insert(newItem2)
modelContext.insert(newItem3)
modelContext.insert(newItem4)
}
}
private func deleteItems(offsets: IndexSet) {
withAnimation {
for index in offsets {
modelContext.delete(items[index])
}
}
}
}
@Model
final class Item {
let id = UUID()
var itemName : String
var sortNr : Int
init(itemName: String, sortNr: Int) {
self.itemName = itemName
self.sortNr = sortNr
}
}
When I use the commented ForEach loop without the sorted(by:..) the list of items is displayed in some random order. The deleting of items removes the respective selected item correctly. I understand that Query and modelContext.insert does not guarantee a specific order, if not specified.
When I use ForEach loop with the sorted(by..) as above the items are displayed in the sorted manner according to the sortNr. But when I swipe to delete one item, most often a "wrong" item is deleted. The offsets is the correct index of the entry I selected, but it seems like the [item] has different indices in the view body than in the deleteItems func.
What do I need to add/change in this cod to have the correct indices in the array. I can use the @Query(sort... as in my app the input to the List view is a dynamic parameter.