SwiftUI嵌套的ForEach会导致致命错误:每个布局项只能出现一次 [英] SwiftUI Nested ForEach causes Fatal error: each layout item may only occur once

查看:243
本文介绍了SwiftUI嵌套的ForEach会导致致命错误:每个布局项只能出现一次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to create a LazyVGrid view to display the contents of objects in an array using nested ForEach statements. The code is causing an app crash with the message "Fatal error: each layout item may only occur once".

每个对象都包含一个值数组,这些值需要在网格中显示为一行.该行包含具有对象sku字符串的单元格,然后是具有对象数组中整数的单元格.

Each object contains an array of values that need to be displayed as a row in the grid. The row consists of cell with the object's sku string followed by a number of cells with the integers from the object's array.

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

I chose to use a class instead of a struct because I need to update the array within the class.

这是数组中对象的类.

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

在代码中,第一个ForEach用于将标头信息放入网格的第一行.

In the code the first ForEach is used to put header information in the first line of the grid.

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

The next ForEach and the ForEach nested in it are causing the error.

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

The outer ForEach iterates through the array of objects so I can create a row in the grid for each object. Each row consists of a string followed values from the roomsForDate array. The size of the roomsForDate array is not fixed.

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

If I comment out the nested ForEach the code executes but with it I get the fatal error.

如果我注释掉Text(roomData.value.description),所以在内部ForEach中没有注释,代码也可以正常运行.如果我将Text(roomData.value.description)替换为Text("),则应用崩溃.

If I comment out Text(roomData.value.description) so there is noting in the inner ForEach, the code runs fine too. If I replace Text(roomData.value.description) with Text("") the app crashes.

ForEach嵌套似乎是从二维数组或每个包含数组的对象数组生成网格视图的最佳方法.

ForEach nesting seems like the best way to accomplish producing a grid view from a two dimensional array or array of objects each containing an array.

我发现其他文章表明嵌套的ForEach语句可以在SwiftUI中使用.

I've found other posts showing that nested ForEach statements can be used in SwiftUI.

这是代码.感谢您在此问题上的帮助.

Here is the code. Your help with this issue is appreciated.

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: {
                        $0 < $1
                    }), 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: { $0.key < $1.key}), id: \.key) { roomData in
                                Text(roomData.value.description)
                            }
                        }
                    }
                }
                .frame(height: 600, alignment: .topLeading)
            }
            .padding(.all, 10)
        }
    }
}

推荐答案

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

Every item in ForEach needs a unique ID. The code can be modified by adding the following line to the Text view in the inner ForEach to assign a unique 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: { $0.key < $1.key}), id: \.key) { roomData in
          Text(roomData.value.description)
            .id("body\(roomPickupData.id)-\(roomData.key)") //<-
          }
        }
       }

这篇关于SwiftUI嵌套的ForEach会导致致命错误:每个布局项只能出现一次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆