首页 > 解决方案 > SwiftUI 集合绑定:从详细列表中删除崩溃并显示“索引超出范围”

问题描述

在 Xcode 13 beta 5 上,我使用今年新推出的ForEach<C>(_ data: Binding<C>, content: @escaping (Binding<C.Element>) -> Content)初始化程序ForEach来填充我的列表。

当我在 iOS 15 设备上的模拟器中运行它时,从详细信息视图中删除按预期工作,当我在 14.7.1 上使用我的设备尝试它时,它会因错误而崩溃

Swift/ContiguousArrayBuffer.swift:580: Fatal error: Index out of range.

注意:根据文档,上面提到的 init 方法应该可以从 iOS 13.0 开始使用——所以我开始认为这是测试版中的一个错误。

现在更奇怪的是,在我的生产应用程序中从列表视图中删除是可行的,而这里的这个示例也对我来说在列表级别崩溃......

有没有其他人看到这个?我应该向苹果报告吗?

import SwiftUI

@main
struct so_deleteFromDetailApp: App {
    @StateObject private var vm = ContentViewModel()
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(vm)
        }
    }
}

struct ContentView: View {
    @EnvironmentObject var vm: ContentViewModel
    var body: some View {
        NavigationView {
            List {
                ForEach($vm.models) { $model in
                    NavigationLink {
                        ContentDetailView(model: $model)
                    } label: {
                        Text(model.id.uuidString)
                    }
                }
                .onDelete { offset in
                    vm.remove(atOffsets: offset) //deleting from the list view works in the real app, but crashes here as well
                }
            }
            .animation(.default)
            .navigationBarItems(trailing: Button(action: {
                vm.add()
            }, label: {
                Label("Add", systemImage: "plus")
            }))
        }
    }
}

struct ContentDetailView: View {
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    @EnvironmentObject var vm: ContentViewModel
    @Binding var model: Model
    var body: some View {
        Text(model.id.uuidString)
            .navigationBarItems(trailing:
                Button {
                vm.remove(model: model) //removing from here crashes the app
                presentationMode.wrappedValue.dismiss()
            } label: {
                Label("Delete", systemImage: "trash")
            })
    }
}
                    
class ContentViewModel: ObservableObject {
    @Published var models: [Model] = {
        var models = [Model]()
        for _ in 0..<5 { models.append(Model()) }
        return models
    }()
    
    func add() {
        models.insert(.init(), at: 0)
    }
    
    func remove(atOffsets offset: IndexSet) {
        models.remove(atOffsets: offset)
    }
    
    func remove(model: Model) {
        models.removeAll(where: { $0.id == model.id })
    }
}

struct Model: Identifiable {
    let id = UUID()
}

struct ContentView_Previews: PreviewProvider {
    static var vm = ContentViewModel()
    static var previews: some View {
        ContentView()
            .environmentObject(vm)
        NavigationView { ContentDetailView(model: .constant(Model()))
                .environmentObject(vm)
        }
    }
}

标签: swiftuiswiftui-list

解决方案


推荐阅读