在动态数组上使用 @Binding 编辑列表(及其包含的项目)时出现问题

问题描述 投票:0回答:1

我遇到了一个问题,最终,某些细节项目上的某些内容变得“不稳定”,当单击它们时不会显示

DetailView

起初,一切都很好,我可以编辑(并查看实时反映的结果)。 我可以重新排序列表,并且可以将

Detail
项目添加到列表中。 然而,过了一段时间,每当我单击某些项目时,我就会开始看到默认的详细视图 (
Text("Select a detail item to view")
)。 我无法预测哪里会发生故障。

在真实的应用程序中,我有一个持久的 JSON 文档,它似乎永远不会被损坏。并反映我执行的编辑。

使用此示例应用程序,我可以通过移动列表中的详细信息项,然后添加详细信息项来非常可靠地触发问题,但是,如果没有这些操作,它最终会失败。

我是否在做“禁止”的事情?

(您可以创建一个新的 Mac 应用程序,并将 ContentView.swift 替换为下面的代码来运行它并使用它)

import SwiftUI

struct ContentView: View {
    @State var main = Main()
    var body: some View {
        NavView(main: $main)
            .onAppear {
                for index in 1..<11 {
                    main.details.append(
                        Detail(
                            title: "Detail \(index)",
                            description: "Description \(index)"))
                }

            }
    }
}

struct NavView: View {
    @Binding var main: Main
    var body: some View {
        NavigationSplitView {
            ListView(main: $main)
        } detail: {
            Text("Select a detail item to view")
        }
    }
}

struct ListView: View {
    @Binding var main: Main
    @State private var addedDetailCount = 0
    var body: some View {
        List($main.details, editActions: .move) { $detail in
            NavigationLink(destination: DetailView(detail: $detail)) {
                Text("\(detail.title)")
            }
        }
        .toolbar {
            Button(
                LocalizedStringKey("Add Detail"), systemImage: "plus"
            ) {
                addedDetailCount += 1
                main.details.append(
                          .init(title: "new Detail \(addedDetailCount)", description: "description"))
            }
        }
    }

}

struct DetailView: View {
    @Binding var detail: Detail
    var body: some View {
        Form {
            Text("id: \(detail.id)")
            TextField("Title", text: $detail.title)
            TextField("Detail", text: $detail.description)
        }
        .padding()
    }
}

struct Main {
    var details = [Detail]()
}

struct Detail: Identifiable {
    var id = UUID()
    var title: String
    var description: String
}

#Preview {
    ContentView()
}
swiftui binding
1个回答
0
投票

根据 Apple 开发人员支持,“在代码片段中将视图目标链接与列表选择混合并匹配将导致未定义的行为”

我需要在

selection
视图上使用
List
参数。

修改后的代码似乎可以正常工作:

import SwiftUI

struct ContentView: View {
    @State var main = Main()
    var body: some View {
        NavView(main: $main)
            .onAppear {
                for index in 1..<11 {
                    main.details.append(
                        Detail(
                            title: "Detail \(index)",
                            description: "Description \(index)"))
                }

            }
    }
}

struct NavView: View {
    @Binding var main: Main
    @State private var selection: UUID?
    var body: some View {
        NavigationSplitView {
            ListView(main: $main, selection: $selection)
        } detail: {
            if let selection {
                DetailView(
                    detail: $main.details.first(where: { $0.id == selection })!)
            } else {
                Text("Select a detail item to view")
            }
        }
    }
}

struct ListView: View {
    @Binding var main: Main
    @State private var addedDetailCount = 0
    @Binding var selection: UUID?
    var body: some View {
        // primary change is here --------------\/
        List($main.details, editActions: .move, selection: $selection) {
            $detail in
            NavigationLink(detail.title, value: detail)
        }
        .toolbar {
            Button(
                LocalizedStringKey("Add Detail"), systemImage: "plus"
            ) {
                addedDetailCount += 1
                main.details.append(
                    .init(
                        title: "new Detail \(addedDetailCount)",
                        description: "description"))
            }
        }
    }
}

struct DetailView: View {
    @Binding var detail: Detail
    var body: some View {
        Form {
            Text("id: \(detail.id)")
            TextField("Title", text: $detail.title)
            TextField("Detail", text: $detail.description)
        }
        .padding()
    }
}

struct Main {
    var details = [Detail]()
}

struct Detail: Identifiable, Hashable {
    var id = UUID()
    var title: String
    var description: String
}

#Preview {
    ContentView()
}
© www.soinside.com 2019 - 2024. All rights reserved.