SwiftUI Strange/unexpected 删除 observedObjects 数组中的元素时的行为

SwiftUI Strange/unexpected behaviour when deleting elements in array of observedObjects

我正在尝试在我尝试开发的应用程序中创建可编辑的 'parts list'。走到这一步是一条艰难的道路 - 许多意想不到的障碍和障碍,现在已经克服了大部分(感谢 'krjw')。
所以,我现在处于可以将项目添加到具有可编辑字段的动态列表的阶段。删除某项后出现问题...无法编辑列表中的后续添加(等于删除的数量)。 为了方便起见,我将相关代码捆绑在一起如下:

import SwiftUI

//  Thanks to KRJW on Whosebug for help getting this far...

struct PartEditView: View {
    @ObservedObject var partToEdit:Part
    var body: some View {
        VStack{
            HStack(alignment: .bottom){
                TextField("Description", text: $partToEdit.description)
                    .frame(width: 350)
                    .padding(.all,5)
                    .cornerRadius(2)
                    .overlay(
                        RoundedRectangle(cornerRadius: 4)
                            .stroke(Color.red, lineWidth: 1))

                Spacer()

                TextField("Price", text: $partToEdit.price).keyboardType(.decimalPad)
                    .frame(width: 80)
                    .padding(.all,5)
                    .cornerRadius(2)
                    .overlay(
                        RoundedRectangle(cornerRadius: 4)
                            .stroke(Color.red, lineWidth: 1))

                Spacer()

                TextField("Quantity", text: $partToEdit.qty).keyboardType(.decimalPad)
                    .frame(width: 60)
                    .padding(.all,5)
                    .cornerRadius(2)
                    .overlay(
                        RoundedRectangle(cornerRadius: 4)
                            .stroke(Color.red, lineWidth: 1))

                Spacer()
                VStack(alignment: .leading){
                    //Text("Line total").font(.caption).padding(.bottom,10)
                    Text(String(format: "%.2f", Double(partToEdit.linePrice)))
                        .frame(width:90,alignment: .leading)
                        .padding(.all,5)
                        .cornerRadius(4)
                        .overlay(
                            RoundedRectangle(cornerRadius: 4)
                                .stroke(Color.blue, lineWidth: 1))
                }
            }
        }
    }
}


class Part: ObservableObject, Identifiable, Equatable {
    static func == (lhs: Part, rhs: Part) -> Bool {
        return lhs.id == rhs.id
    }
    //part line item (desc, price, qty, line price)
    @Published var id: UUID
    @Published var description:String
    @Published var price:String
    @Published var qty:String
    var linePrice:Double{
        let itemPrice = Double(price) ?? 0
        let quantity = Double(qty) ?? 0
        return itemPrice * quantity
    }
    init(id:UUID, description:String, price:String, qty:String) {
        self.id = id
        self.description = description
        self.price = price
        self.qty = qty
    }
}


struct ContentView: View {
    @State var parts = [Part]()

    var body: some View {
        VStack{
            HStack{
                Text("Add line ")

                Image(systemName: "plus.circle").font(.largeTitle)
                    .onTapGesture {
                        let newPart:Part = Part(id: UUID(), description: "any.....thing", price: "", qty: "1")
                        self.parts.append(newPart)
                }
            }

            List{
                ForEach(parts){part in
                    PartEditView(partToEdit: part)
                }.onDelete(perform: deleteRow)
            }
            HStack{
                Spacer()
                Text("Total: ")
                Text(String(self.parts.reduce(0){[=11=] + .linePrice}))
            }
            Spacer()
        }
    }
    func deleteRow(at offsets: IndexSet){
        self.parts.remove(atOffsets: offsets)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

我怀疑数组索引以某种方式混淆了。
如果有人能对此有所了解,我将不胜感激。

该行似乎没有更新。我已经通过向具有所有 TextFields 的 PartEditView HStack 添加一个 id 来解决它,如下所示:

struct PartEditView: View {
    @ObservedObject var partToEdit:Part
    var body: some View {
        VStack{
            HStack(alignment: .bottom){
                TextField("Description", text: $partToEdit.description)
                    .frame(width: 350)
                    .padding(.all,5)
                    .cornerRadius(2)
                    .overlay(
                        RoundedRectangle(cornerRadius: 4)
                            .stroke(Color.red, lineWidth: 1))

                Spacer()

                TextField("Price", text: $partToEdit.price).keyboardType(.decimalPad)
                    .frame(width: 80)
                    .padding(.all,5)
                    .cornerRadius(2)
                    .overlay(
                        RoundedRectangle(cornerRadius: 4)
                            .stroke(Color.red, lineWidth: 1))

                Spacer()

                TextField("Quantity", text: $partToEdit.qty).keyboardType(.decimalPad)
                    .frame(width: 60)
                    .padding(.all,5)
                    .cornerRadius(2)
                    .overlay(
                        RoundedRectangle(cornerRadius: 4)
                            .stroke(Color.red, lineWidth: 1))

                Spacer()
                VStack(alignment: .leading){
                    //Text("Line total").font(.caption).padding(.bottom,10)
                    Text(String(format: "%.2f", Double(partToEdit.linePrice)))
                        .frame(width:90,alignment: .leading)
                        .padding(.all,5)
                        .cornerRadius(4)
                        .overlay(
                            RoundedRectangle(cornerRadius: 4)
                                .stroke(Color.blue, lineWidth: 1))
                }
            }
            .id(partToEdit.id)
        }
    }
}

这样,行将针对每个 Part 进行更新。 SwiftUI 不会重新使用之前删除的行,而是会创建一个新行。