I’ve an array of transaction entries which can be sorted by date. Including and viewing entries works wonderful, however when deleting an entry, the incorrect entry is eliminated. (No error messages are generated.) I observed whereas observing the code with breakpoints and single-stepping that the entry offset utilized by the sorted array is handed to onDelete as a substitute of the truly saved array offset. On-line, I discovered an instance much like mine utilizing coreData / swiftData, however I could not discover something on easy methods to go the proper offset to onDelete.
Beneath is my code, together with the mannequin and viewModel.
struct ContentView: View {
@Atmosphere(WithdrawalModel.self) non-public var wdvm
let frmt: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "MMM dd, yyyy"
return formatter
}()
func bankEntries(for date: String) -> [Withdrawal] {
return wdvm.wdArray.filter { frmt.string(from: $0.wdDate) == date }
}
// creates an inventory of distinctive dates (no duplicates)
var uniqueDates: [String] {
Array(Set(wdvm.wdArray.map { frmt.string(from: $0.wdDate) }))
.sorted { frmt.date(from: $0) ?? Date() < frmt.date(from: $1) ?? Date() }
.compactMap { $0 }
}
@State non-public var charges: Double = 0.0
var physique: some View {
NavigationStack {
GeometryReader { g in
VStack (alignment: .main) {
if !wdvm.wdArray.isEmpty {
HStack {
Textual content("Time/Location")
.padding(.main, g.measurement.width * 0.1)
Textual content("Native/Residence")
.padding(.main, g.measurement.width * 0.104)
}
Record {
// outer ForEach with distinctive dates
ForEach(uniqueDates, id: .self) { dateItem in
Part {
// internal ForEach with gadgets of this date
ForEach(bankEntries(for: dateItem)) { merchandise in
RowView(merchandise: merchandise)
}
} header: {
// show date as soon as for all entries with the identical date
Textual content("(dateItem)")
}
}
.onDelete(carry out: deleteItem)
}
} else {
Textual content("No Withdrawal Entries")
.padding(.high, g.measurement.top * 0.35)
}
}
.toolbar {
ToolbarItem(placement: .principal) {
Textual content("ATM Withdrawals")
.foregroundStyle(Coloration.black)
}
ToolbarItem(placement: .navigationBarTrailing) {
NavigationLink {
AddWithdrawalView()
} label: {
Picture(systemName: "plus")
.imageScale(.giant)
.symbolRenderingMode(.hierarchical)
}
}
}
.toolbarBackground(Coloration.orange, for: .navigationBar)
.toolbarBackground(.seen, for: .navigationBar)
.toolbar(.hidden, for: .tabBar)
}
}
}
/*---------------------------------------
might delete withdrawal entries with swipe left
---------------------------------------*/
func deleteItem(at offsets: IndexSet) {
offsets.forEach { singleOffset in
wdvm.wdArray.take away(atOffsets: offsets)
}
}
}
// withdrawal mannequin
struct Withdrawal: Codable, Identifiable {
var id: UUID
var wdDate: Date
var wdCode: String
var wdBank: String
var wdAmtL: Double
var wdAmtH: Double
init(id: UUID = UUID(), wdDate: Date, wdCode: String, wdBank: String, wdAmtL: Double, wdAmtH: Double) {
self.id = id
self.wdDate = wdDate
self.wdCode = wdCode
self.wdBank = wdBank
self.wdAmtL = wdAmtL
self.wdAmtH = wdAmtH
}
}
// Withdrawal ViewModel
@Observable closing class WithdrawalModel {
var wdArray: [Withdrawal] {
didSet {
// save withdrawal entries
if let encoded = strive? JSONEncoder().encode(wdArray) { // save withdrawal entries
UserDefaults.customary.set(encoded, forKey: StorageKeys.wdBank.rawValue)
}
}
}
init() {
if let wdArray = UserDefaults.customary.knowledge(forKey: StorageKeys.wdBank.rawValue) {
if let decoded = strive? JSONDecoder().decode([Withdrawal].self, from: wdArray) {
self.wdArray = decoded
return
}
}
self.wdArray = []
}
/*---------------------------------------
save new withdrawal knowledge
---------------------------------------*/
func addNewWithdrawal(wdDate: Date, wdCode: String, wdBank: String, wdAmtL: Double, wdAmtH: Double) -> () {
let merchandise = Withdrawal(wdDate: wdDate, wdCode: wdCode, wdBank: wdBank, wdAmtL: wdAmtL, wdAmtH: wdAmtH)
wdArray.append(merchandise)
if let encoded = strive? JSONEncoder().encode(wdArray) {
UserDefaults.customary.set(encoded, forKey: StorageKeys.wdBank.rawValue)
}
}
}