SwiftUI Nested ForEach causes Fatal error: each layout item may only occur once

SwiftUI Nested ForEach causes Fatal error: each layout item may only occur once

我正在尝试创建一个 LazyVGrid 视图,以使用嵌套的 ForEach 语句显示数组中对象的内容。该代码导致应用程序崩溃并显示消息“致命错误:每个布局项可能只出现一次”。

每个对象都包含一组需要在网格中显示为一行的值。该行由带有对象 sku 字符串的单元格组成,后跟一些带有对象数组中整数的单元格。

我选择使用 class 而不是结构,因为我需要更新 class 中的数组。

这是数组中对象的 class。

class RoomPickupData: Identifiable {
    let id = UUID()
    var sku: String = ""
    // Array of counts for sku on a particular date
    var roomsForDate: [Date: Int] = [:]
}

代码中第一个ForEach用于将表头信息放在网格的第一行。

下一个 ForEach 和嵌套在其中的 ForEach 导致错误。

外部 ForEach 遍历对象数组,因此我可以在网格中为每个对象创建一行。每行都包含一个字符串,后跟 roomsForDate 数组中的值。 roomsForDate 数组的大小不固定。

如果我注释掉嵌套的 ForEach,代码会执行,但会出现致命错误。

如果我注释掉 Text(roomData.value.description) 所以在内部 ForEach 中有注释,代码也运行良好。如果我用 Text("") 替换 Text(roomData.value.description) 应用程序崩溃。

ForEach 嵌套似乎是从二维数组或对象数组中生成网格视图的最佳方式,每个对象数组都包含一个数组。

我发现其他帖子表明可以在 SwiftUI 中使用嵌套的 ForEach 语句。

这是代码。感谢您对此问题的帮助。

struct RoomTableView: View {
    @ObservedObject var checkfrontVM: CheckFrontVM
    let dateFormatter = DateFormatter()
    
    init(checkfrontVM: CheckFrontVM) {
        self.checkfrontVM = checkfrontVM
        dateFormatter.dateFormat = "MM/dd/yyyy"
    }
    
    func initColumns() -> [GridItem] {
        var columns: [GridItem]
        var columnCount = 0
        
        if self.checkfrontVM.roomPickupDataArray.first != nil {
            columnCount = self.checkfrontVM.roomPickupDataArray.first!.roomsForDate.count
        } else {
            return []
        }
        columns = [GridItem(.flexible(minimum: 100))] + Array(repeating: .init(.flexible(minimum: 100)), count: columnCount)
        return columns
    }
    
    var body: some View {
        if self.checkfrontVM.roomPickupDataArray.first != nil {
            ScrollView([.horizontal, .vertical]) {
                
                LazyVGrid(columns: initColumns()) {
                    Text("Blank")
                    ForEach(self.checkfrontVM.roomPickupDataArray.first!.roomsForDate.sorted(by: {
                        [=11=] < 
                    }), id: \.key) { roomData in
                        Text(dateFormatter.string(from: roomData.key))
                    }
                    
                    ForEach(self.checkfrontVM.roomPickupDataArray) { roomPickupData in
                        Group {
                            Text(roomPickupData.sku)
                                .frame(width: 80, alignment: .leading)
                                .background(roomTypeColor[roomPickupData.sku])
                                .border(/*@START_MENU_TOKEN@*/Color.black/*@END_MENU_TOKEN@*/)
                            ForEach(roomPickupData.roomsForDate.sorted(by: { [=11=].key < .key}), id: \.key) { roomData in
                                Text(roomData.value.description)
                            }
                        }
                    }
                }
                .frame(height: 600, alignment: .topLeading)
            }
            .padding(.all, 10)
        }
    }
}

ForEach 中的每个项目都需要一个唯一的 ID。可以通过在内部 ForEach 的文本视图中添加以下行来修改代码以分配唯一 ID:

.id("body\(roomPickupData.id)-\(roomData.key)")

ForEach(self.checkfrontVM.roomPickupDataArray) { roomPickupData in
    Group {
        Text(roomPickupData.sku)
        .frame(width: 80, alignment: .leading)
           .background(roomTypeColor[roomPickupData.sku])
           .border(Color.black)
        ForEach(roomPickupData.roomsForDate.sorted(by: { [=10=].key < .key}), id: \.key) { roomData in
          Text(roomData.value.description)
            .id("body\(roomPickupData.id)-\(roomData.key)") //<-
          }
        }
       }

我在 LazyVStack 中的 ForEach 中遇到了 ForEach 的相同错误 我已经通过将 UUID() 标识符添加到最里面的视图解决了它

.id(UUID)

这是一个例子:

LazyVStack {
    ForEach(vmHome.allCategories, id: \.self) { category in
        VStack {
            HStack {
                Text(category)
                    .font(.title3)
                    .bold()
                    .padding(10)
                Spacer()
            }
            ScrollView(.horizontal) {
                LazyHStack{
                    ForEach(vmHome.getMovies(forCat: category), id: \.self.id) { movie in
                         StandardHomeMovieView(movie: movie)
                             .id(UUID())
                     }
                }
            }
        }
    }
}