删除最后一个数组元素时,SwiftUI 列表 ForEach 索引超出范围

问题描述

我目前正在学习 SwiftUI,但遇到了这个我似乎无法解决的问题。可能有一个非常简单的解决方案。本质上,我有一个包含 NSManagedobjects (Room) 列表的视图模型:

class Roomviewmodel: ObservableObject,viewmodelProtocol {
    
    enum ViewState {
        case Loading
        case normal
        case NoData
    }
    
    @Published var viewState: ViewState = .Loading
    @Published var rooms: [Room] = []
    
    // Get all the rooms
    func getRooms() {
        viewState = .Loading
        rooms = CoreDataManager.shared.getRooms()
        updateViewState()
    }
    
    // MARK: Update the view state
    func updateViewState() {
        viewState = rooms.count == 0 ? .NoData : .normal
    }
}

从视图模型中的房间列表中删除最后一个元素时,foreach 崩溃:

if viewmodel.rooms.count > 0 {
    List {
        ForEach(Array(viewmodel.rooms.enumerated()),id: \.self.element.id) { index,room in
            Roomrow(room: self.viewmodel.rooms[index],viewmodel: viewmodel,index: index)
        }.listRowBackground(Color.backgroundColor)
    }
} else {
    NoData()
}

当我删除一个房间时,这是运行的代码

PersistenceController.shared.container.viewContext.delete(self.viewmodel.rooms[selectedindex])
self.viewmodel.rooms.remove(at: selectedindex)
PersistenceController.shared.saveContext()

然后应用程序在视图中的 ForEach 循环中崩溃,指出索引超出范围。这是一些异步问题吗,viewState 在元素从 viewmodel 的列表中删除之前更新?

解决方法

我找到了解决问题的方法。问题似乎是 ForEach 试图查看先前数据和新数据之间的差异,并试图获取已删除的核心数据对象。我通过更改 ForEach 循环来检查我们正在查看的对象是否已被删除来解决此问题

ForEach(Array(viewModel.rooms.enumerated()),id: \.self.element.id) { index,room in
    if room.isFault {
        EmptyView()
    } else {
        RoomRow(room: self.viewModel.rooms[index],viewModel: viewModel,index: index)
    }
}