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

Posted

技术标签:

【中文标题】删除最后一个数组元素时,SwiftUI列表ForEach索引超出范围【英文标题】:SwiftUI list ForEach index out of range when last array element deleted 【发布时间】:2020-12-23 16:33:24 【问题描述】:

我现在正在学习 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 在从视图模型的列表中删除元素之前更新?

【问题讨论】:

这是否回答了您的问题***.com/a/61435489/12299030、***.com/a/61431459/12299030? @Asperi 不是真的,这个解决方案需要你创建一个绑定,而我不想要一个绑定,而只是将一个变量传递给另一个视图。 self.viewModel.updateViewState() 是 UIKit 的想法。在 SwiftUI 中,您需要创建自动管理状态的变量。 medium.com/flawless-app-stories/… 很公平,但即使没有所有代码,foreach 在删除视图模型中房间列表中的最后一个元素时也会崩溃。 【参考方案1】:

我找到了解决问题的方法。问题似乎是 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)
    

【讨论】:

以上是关于删除最后一个数组元素时,SwiftUI列表ForEach索引超出范围的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI - 删除绑定数组中的元素会导致错误

SwiftUI - 致命错误:从数组中删除元素时索引超出范围

当列表填充数组时,如何在 SwiftUI 中获取列表中元素的索引?

从 SwiftUI 的列表中删除列表元素

从 SwiftUI 的列表中删除列表元素

删除嵌套属性中的元素时更新 SwiftUI 列表