每个可识别的结构对象属性进入列表的类别(按categoryName排序)

时间:2019-12-30 03:38:30

标签: struct foreach swiftui

我觉得我在这里遗漏了一些明显的东西,但是我已经坚持了几天,似乎无法找到答案。

1。)我正在使用一个单独的swift文件,该文件带有可识别的Struct,该对象具有带有两个Struct属性的对象,即 name categoryName 。 (旁注,我在对象中使用 var 而不是 let ,因为不能使用.onMove修饰符将其作为常量来重新排列行)

    //STRUCT

struct Item: Identifiable {
    var id = UUID()
    var name: String
    var categoryName: String
}



//OBJECT

var items : [Item] = [

    //CLOTHING
    Item(name: "Hats", categoryName: "Clothing"),
    Item(name: "Shirts", categoryName: "Clothing"),
    Item(name: "Pants", categoryName: "Clothing"),

    //Electronics
    Item(name: "Macbook", categoryName: "Electronics"),
    Item(name: "Macbook Adapter", categoryName: "Electronics"),
    Item(name: "iPhone", categoryName: "Electronics"),


]

2。)在swiftui文件中,我有以下代码来构建列表,使用嵌套的ForEach循环拉出categoryName,将其添加到Section标头,然后再另一个以循环出项目。

    //List code

 NavigationView {
            List {
                ForEach(items) { currentItem in
                    Section(header: Text(currentItem.categoryName)){
                        ForEach(items) { currentItem in
                             NavigationLink(destination: ItemDetail(itemData: currentItem)){ ItemRow(item: currentItem)

                            }
                        }

不幸的是,我得到的是一个可笑的结果。

enter image description here

我在节标题中得到了我的categoryName,并在下面列出了我的项目。实际上,无论类别如何,我都会获得下面列出的所有项目。然后,这些部分将以非常混乱的方式打印出与对象数组中的行完全相同的次数。

在这种情况下,我有6行,所以我得到6行。但是,在2个categoryName字符串“服装”和“电子产品”中,它们将分别打印3次。

感觉有一种简单的方法“为items.categoryName中的每个categoryName添加一个标题到该部分并列出相应的名称”-但我不会破解它。

希望这里的人可以指出我做错了什么。

2 个答案:

答案 0 :(得分:1)

您拥有平面数组,并对其进行了多次迭代,因此结果也将平面乘以多次。

好吧,对于您选择的模型,即items,可以通过以下操作来达到您想要完成的结果...

List {
    ForEach(Array(Set(items.compactMap{ $0[keyPath: \.categoryName] })), id: \.self) { category in
        Section(header: Text(category)) {
            ForEach(items.filter { $0.categoryName == category }) { currentItem in
                 NavigationLink(destination: Text("ItemDetail(itemData: currentItem)")){ Text("\(currentItem.name)") }
                }
            }
        }
}
.listStyle(GroupedListStyle())

但是我会为items选择不同的模型,即字典为[categoryName: Item]

答案 1 :(得分:1)

您可以按类别对阵列进行分组:

let sections = Dictionary(grouping: items) { $0.categoryName }

然后您可以像使用它一样

var keys: [String] = { sections.map {$0.key} }

var body: some View {
    List {
        ForEach(keys, id: \.self) { section in
            Section(header: Text(section)){
                ForEach(self.sections[section] ?? []) { currentItem in
                    Text(currentItem.name)
                }
            }
        }
    }
}

请注意,我已经简化了您的代码,使其可以在我的计算机上运行,​​但是更改并未影响答案