SwiftUI / .onDelete 嵌套数组列表中的子 OutlineGroup 行

SwiftUI / .onDelete child OutlineGroup row in a List from a nested array

我正在创建一个使用 OutlineGroup 呈现嵌套数组的列表。我正在尝试对此 ForEach 循环实施 .onDelete。

Interface UI

.onDelete 在此 ForEach 循环中无法正常工作。

可以正确删除顶级行,但不能正确删除子级行。

我认为 IndexSet 没有正确定位 focusExample[subFocus]。 (当我尝试时出现错误)

如何让 .onDelete 在此 OutlineGroup 中正常工作?

struct FocusArea: Identifiable {
    let id = UUID()
    let focus: String
    let time: Int
    let subFocus: [FocusArea]?
    
}

struct FocusView: View {
 @State private var focusExample =
    [   FocusArea(focus: "PhD", time: 20, subFocus: [
                FocusArea(focus: "Experimenting", time: 15, subFocus: nil),
                FocusArea(focus: "Writing", time: 5, subFocus: nil)
            ]),

        FocusArea(focus: "Reading", time: 10, subFocus:[
                FocusArea(focus: "Holes", time: 7, subFocus: nil),
                FocusArea(focus: "Harry Potter", time: 3, subFocus: nil)
            ]),

        FocusArea(focus: "Piano", time: 5, subFocus: nil)
    ]
    
    func delete(at offset: IndexSet) {
        focusExample.remove(atOffsets: offset)
    }

    var body: some View {
        NavigationView{
            List{
                ForEach(focusExample) { focus in
                        OutlineGroup(focus, children: \.subFocus) { subFocus in
                            HStack {
                                Text(subFocus.focus)
                                Spacer()
                                Group {
                                    Text("\(focus.time)")
                                        .font(Font.system(.body, design: .rounded).weight(.medium))
                                    +
                                    Text(" HR")
                                        .font(Font.system(.body, design: .rounded).weight(.medium).smallCaps())
                                }.foregroundColor(Color.green)
                            
                            }
                            
                        }
                }.onDelete(perform: delete)
 
            }
            .toolbar {
                EditButton()
            }
            .navigationTitle("Focus")
        }
        
    }
}

OutlineGroup本身就是一个完整的视图。它不需要 ForEach 围绕它。
(实际上,在您的代码中,您可以删除 ForEach,一切都会照常进行。)

这也意味着,(到目前为止)它不处理编辑模式,也不处理 .onDelete

但是:如果您只需要两个层级(父级 - 子级),您可以使用 ForEachDisclosureGroup 来实现并获得您想要的结果:)

var body: some View {
    NavigationView{
        List{
            // outer ForEach for parents, binding! for delete to work
            ForEach($focusExample) { $focus in
                DisclosureGroup {
                    // Inner ForEach for children
                    ForEach(focus.subFocus ?? []) { subFocus in
                        focusCell(focus: subFocus)
                    }
                    .onDelete { indices in
                        // delete for children
                        focus.subFocus?.remove(atOffsets: indices)
                    }

                } label: {
                    focusCell(focus: focus)
                }
            }
            .onDelete { indices in
                // delete for parents
                focusExample.remove(atOffsets: indices)
            }
        }
        .toolbar {
            EditButton()
        }
        .navigationTitle("Focus")
    }
}

// your original formatting, just factored out
func focusCell(focus: FocusArea) -> some View {
    HStack {
        Text(focus.focus)
        Spacer()
        Group {
            Text("\(focus.time)")
                .font(Font.system(.body, design: .rounded).weight(.medium))
            +
            Text(" HR")
                .font(Font.system(.body, design: .rounded).weight(.medium).smallCaps())
        }.foregroundColor(Color.green)
    }
}