0

I am trying to create an editable 'parts list' in an app I'm trying to develop. It's been a rough road getting this far - many unexpected hurdles and obstacles, most of which have now been overcome (thanks to 'krjw').
So, I'm now at a stage where items can be added to a dynamic list with editable fields. The problem arises after an item is deleted...subsequent additions to the list (equal to the number of deletions) cannot be edited. I've bundled the relevant code together for convenience below:

import SwiftUI

//  Thanks to KRJW on StackOverflow 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){$0 + $1.linePrice}))
            }
            Spacer()
        }
    }
    func deleteRow(at offsets: IndexSet){
        self.parts.remove(atOffsets: offsets)
    }
}

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

I suspect that array indexing is somehow getting mixed up.
If anyone can shed any light on this I'd very much appreciate it.

4

1 回答 1

0

看起来该行没有更新。我已经通过向PartEditView具有所有 TextFields 的 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 不会重新使用之前删除的行,而是会创建一个新行。

于 2020-02-14T01:10:34.773 回答