SwiftUI 列表“NSInternalInconsistencyException",原因:“尝试插入第 0 节,但更新后只有 0 节"

人气:680 发布:2022-10-16 标签: swiftui xcode13

问题描述

我有以下代码.它需要 Xcode 13 beta 才能编译.在 iOS 14 上运行并点击插入数据"时按钮,它崩溃并出现以下错误:

I have the following code. It needs the Xcode 13 beta to compile. When running on iOS 14 and tapping the "Insert data" button, it crashes with the following error:

libc++abi: terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to insert section 0 but there are only 0 sections after the update'
terminating with uncaught exception of type NSException

class MyViewModel: ObservableObject {
    @Published var components: [String] = []
}

struct ComponentListContent: View {
    @EnvironmentObject var viewModel: MyViewModel

    var body: some View {
        ForEach(self.$viewModel.components, id: \.self) { $component in // This syntax requires Xcode 13
            TextField("Component Name", text: $component)
        }
    }
}

struct MySheet: View {
    @EnvironmentObject var viewModel: MyViewModel
    @State private var isSheetPresented = true
    @State var isEditing = false

    var body: some View {
        NavigationView {
            List {
                ComponentListContent()
            }
            .environment(\.editMode, .constant(self.isEditing ? EditMode.active : EditMode.inactive))
            .navigationBarItems(trailing:
                Button(action: { self.isEditing.toggle() }, label: {
                    Text(self.isEditing ? "Done" : "Edit")
                })
            )
            .sheet(isPresented: self.$isSheetPresented) {
                Button("Insert data") {
                    self.isSheetPresented.toggle()
                    self.viewModel.components = ["a", "b", "c", "d"]
                }
            }
            .navigationBarTitle("New Analysis", displayMode: .inline)
        }
        .navigationViewStyle(StackNavigationViewStyle())
    }
}

struct ContentView: View {
    var body: some View {
        Text("Hello, world!")
            .sheet(isPresented: .constant(true)) {
                MySheet()
                    .environmentObject(MyViewModel())
            }
    }
}

如果我将 ComponentListView 的主体移动到 MySheet 中,则不会发生错误.如果我删除 .environment(\.editMode....,它也不会发生.但是我确实需要这两个.是否存在我遗漏的潜在问题?

If I move the body of ComponentListView into MySheet, the error doesn't occur. If I remove the .environment(\.editMode...., it also doesn't occur. However I do need both of these. Is there an underlying issue that I am missing?

推荐答案

这似乎是由于 .constant 绑定而发生的.

This seems happening because of .constant binding.

我建议您切换到存储 EditMode 而不是 Bool,并使用将修改它的 getter/setter 定义 isEditing.你可以用 @Binding 做同样的事情,但这看起来更简洁.

I suggest you switching to storing EditMode instead of Bool, and define isEditing with getter/setter that will modify it. You could do the same with @Binding, but this looks a little cleaner.

@State var editMode = EditMode.inactive
var isEditing: Bool {
    get {
        editMode.isEditing
    }
    nonmutating set {
        if newValue {
            editMode = .active
        } else {
            editMode = .inactive
        }
    }
}

// subscribe
.environment(\.editMode, $editMode)

250