I have a ForEach that I use to display some info, sorted on it’s date attribute:
My view looks like:
ForEach(records.sorted(by: < ), id: .self) { record in
Text("(record.date")
}
.onDelete(perform: deleteRecord)
Record.swift
class Record : Comparable {
var value: Float
var date: Date
init(value: Float = 0.0, date: Date = Date.now) {
self.value = value
self.date = date
}
static func < (lhs: Record, rhs: Record) -> Bool {
return lhs.date < rhs.date
}
}
My problem is that whenever I delete an item, the wrong one is actually removed.
deleteRecord()
func deleteRecord(_ indexSet: IndexSet) {
for index in indexSet {
movement.records.remove(at: index)
}
}
I’v tried changing the deleteRecord()
method to something like:
func deleteRecord(at offsets: IndexSet) {
movement.records.remove(atOffsets: offsets)
}
but this did not solved my issue.
3
Answers
I managed to make a simple solution:
First I sorted the ForEach like this:
After that, in
deleteRecord()
:You can sort the record array not on the ForEach but after you add the records.
Remove the
.sorted(by: < )
from the ForEach and add it to the end of the data fetching. And it should work like a charm.Warning: You should create a temporary array, sort the temporary array and then save it to records so it doesn’t do some weird moving animations.
Tip: You should use structs instead of classes. Because classes are reference type and structs are value type.
More info about it here: Value And Reference Types In Swift
Problem
The index of your sorted array and the original index of the
records
data are different. That’s why you are removing wrong item.Solution
You can make a conversion of your sorted item index to the original index in your delete function. I’m sharing the demo code:
Note this is a demo code, because I don’t know what’s your
movement
property is doing, or any other details which you haven’t shared. I guess you can update your code according to this demo.