Swift 根据类别使用ForEach获取多个DisclosureGroup
问题描述
我现在正在构建一个视图,我尝试根据类别使用ForEach获取多个DisclosureGroup。这是容易的部分。我的问题在于第二个数组,我想要获取具有指定类别的项目。
代码如下:
@Environment(\.modelContext) var context
@Query private var category: [CategoryModel]
@Query private var bonsai: [BonsaiModel]
@State private var searchQuery = ""
var body: some View {
NavigationStack {
VStack {
}
VStack(alignment: .center) {
List {
Section {
// Query category to build DisclosureGroup
ForEach(category) { categories in // Loop through category
DisclosureGroup(categories.name) {
ForEach(bonsai) { items in // Loop through bonsai, where bonsai.category = category
Text(items.name)
.bold()
if let category = items.category {
Text(category.name) // show category.title
.foregroundColor(Color(.systemGray))
.bold()
} else {
Text(" ")
.padding(.top, 4)
}
}
}
}
}
}
.padding(.horizontal, 8)
.padding(.top, 8)
.listStyle(.inset)
我在其中放了两个文本项,以查看我尝试在“bonsai” ForEach中获取的数据。
这里有一张图片,来展示我试图实现的目标:
现在你可以看到全部内容,但是你可以将类别用作“过滤器”,只在它们的组内显示。
我猜它可能会用到compactMap或filter,但我不知道如何让它起作用。
这里是模型:
@Model
final class BonsaiModel {
var uuid: UUID
var timestamp: Date
var purchased: Date
var price: Double
var name: String
var isFavorite: Bool
var age: String
@Attribute(.externalStorage)
var bonsaiImageData: Data?
@Relationship(deleteRule: .nullify, inverse: \CategoryModel.bonsai)
var category: CategoryModel?
@Relationship(deleteRule: .nullify, inverse: \SpeciesModel.bonsai)
var species: SpeciesModel?
init(price: Double = 0.00,
name: String = "",
isFavorite: Bool = false,
age: String = "",
bonsaiImageData: Data? = nil
) {
self.uuid = UUID()
self.timestamp = Date()
self.purchased = Date()
self.price = price
self.name = name
self.isFavorite = isFavorite
self.age = age
self.bonsaiImageData = bonsaiImageData
}
}
@Model
final class CategoryModel {
@Attribute(.unique) var name: String = ""
var bonsai: [BonsaiModel]?
init(name: String) {
self.name = name
}
}
@Model
final class SpeciesModel {
@Attribute(.unique) var name: String = ""
var bonsai: [BonsaiModel]?
init(name: String) {
self.name = name
}
}
解决方案
鉴于您的数据模型,您可以直接访问CategoryModel中的BonsaiModel的关联属性,这样您只会获得属于当前CategoryModel的对象,而无需执行任何过滤或匹配对象的操作。
ForEach(category) { categories in
DisclosureGroup(categories.name) {
ForEach(categories.bonsai ?? []) { items in
Text(items.name)
//...
}
}
}
旁注:我建议将关系的多方面设为非可选项
var bonsai: [BonsaiModel] = []
同时,通过这种解决方案您还可以从视图中删除对BonsaiModel的查询