在 SwiftUI 的列表中按类别对核心数据项进行分组

问题描述 投票:0回答:1

我有一个核心数据容器,其中包含两个实体:一个类别和一个项目。项目可以分配一个类别,并且类别可以分配给多个项目。

我需要做的是在 SwiftUI 的列表中按类别对项目进行分组。

下面的代码不会按类别对所有项目进行分组,它只按类别显示一项。如何将具有相同类别的所有项目分组到同一类别组下?

核心数据实体

Category
    Attributes
        name
    Relationship
        items (Type: To Many)

Item
    Attributes
        name
    Relationship
        category (Type: To One)

Swiftui

struct ItemsView: View {
    let selectedList:List

    @EnvironmentObject private var itemSM: ItemServiceModel
    
    var body: some View {
        List{
            ForEach(itemSM.items){ item in
                Section(header: Text(item.category?.name ?? "")) {
                    Text("\(item.name ?? "")")
                }
            }
        }
        .onAppear{
           itemSM.loadItems(forList: selectedList)
       }
    }
}

服务项目服务模式

class ItemServiceModel: ObservableObject{
    let manager: CoreDataManager
    @Published var items: [Item] = []

    func loadItems(forList list: List){
        let request = NSFetchRequest<Item>(entityName: "Item")
        
        let sort = NSSortDescriptor(keyPath: \Item.name, ascending: true)
        request.sortDescriptors = [sort]
        
        let filter = NSPredicate(format: "list == %@", list)
        request.predicate = filter

        do{
            items =  try manager.context.fetch(request)
        }catch let error{
            print("Error fetching items. \(error.localizedDescription)")
        }
    }
}

这就是我所看到的:如您所见,

Grapes
Oranges
应该位于同一组
Fruits & Vegetables

编辑1

添加了

loadItems()
方法和图像。

编辑2

ForEach
内添加额外的
Section
我能够对项目进行分组,我现在的问题是它为数组中的项目总数添加了一个部分。

List {
    ForEach(itemSM.items) { item in
        Section(header: Text(item.category?.name ?? "")) {
            ForEach(itemSM.items.filter { $0.category == item.category }) { filteredItem in
                Text("\(filteredItem.name ?? "")")
            }
        }
    }
}

这就是我所看到的,正如您所看到的,应该只存在一个

Fruits & Vegetables
部分。

swift swiftui core-data
1个回答
0
投票

这对我有用。它基本上返回并显示指定列表中的所有类别及其各自的项目。

类别服务模型

func loadCategories(for list: List) -> ([Category], [Item]) {
    let request = NSFetchRequest<Category>(entityName: "Category")

    let predicate = NSPredicate(format: "ANY items IN %@", list.items ?? [])
    request.predicate = predicate

    let sort = NSSortDescriptor(keyPath: \Category.name, ascending: true)
    request.sortDescriptors = [sort]

    do {
        let categories = try manager.context.fetch(request)
        var categories: [Category] = []
        var items: [Item] = []

        for category in categories {
            categories.append(category)
            if let items = category.items?.allObjects as? [Item] {
                let filteredItems = items.filter { $0.list == list }
                items.append(contentsOf: filteredItems)
            }
        }

        return (categories, items)
    } catch let error {
        print("Error fetching categories. \(error.localizedDescription)")
        return ([], [])
    }
}

SwiftUI

  List {
      ForEach(categorySM.categories) { category in
          Section(header:Text(category.name ?? "")){
              ForEach(category.items?.allObjects as? [Item] ?? []) { item in
                  Text("\(item.name ?? "")")
              }
          }
      }
  }
  .onAppear{
      categorySM.loadCategories(for: selectedList)
  }
© www.soinside.com 2019 - 2024. All rights reserved.