I am attempting to place drugs under sections correlating to their class but I’m getting multiple sections for each drug I add of the same class. I’m not sure how much this process differs when using model macros.
List {
ForEach(activeStash) { drug in
Section(header: Text(drug.substanceClass)) {
NavigationLink(destination: StashLinkView(stashed: drug)) {
Text(drug.substance)
}
}
}
}
Grouping but with duped sections Result:
List {
ForEach(activeStash) { drug in
Section(header: Text(drug.substanceClass)) {
ForEach(activeStash) { drug in
NavigationLink(destination: StashLinkView(stashed: drug)) {
Text(drug.substance)
}
}
}
}
}
Solution:
List {
ForEach(Array(Set(activeStash.map { $0.substanceClass })), id: \.self) { substanceClass in
Section(header: Text(substanceClass)) {
ForEach(activeStash.filter { $0.substanceClass == substanceClass }) { drug in
NavigationLink(destination: StashLinkView(stashed: drug)) {
Text(drug.substance)
}
}
}
}
}
Your first ForEach
needs to filter the available substance classes (the sections), the second filters drugs by their substance class to appear in the correct section:
struct Drug: Identifiable, CustomStringConvertible {
let substance: String
let substanceClass: SubstanceClass
let id: UUID = UUID()
var description: String {
"Drug: \(substance) (\(substanceClass))"
}
}
enum SubstanceClass: String, CaseIterable, Identifiable {
case stimulant = "Stimulant"
case sedative = "Sedative"
var id: String {
self.rawValue
}
}
struct ContentView: View {
@State var substances: [Drug] = [
Drug(substance: "Caffeine", substanceClass: .stimulant),
Drug(substance: "Adrafinil", substanceClass: .stimulant),
Drug(substance: "Valerian", substanceClass: .sedative)
]
var body: some View {
VStack {
Text("Drug Store")
List {
ForEach(SubstanceClass.allCases) { substanceClass in
Section(header: Text(substanceClass.rawValue)) {
ForEach(substances.filter({$0.substanceClass == substanceClass})) { drug in
NavigationLink(destination: Detail(drug: drug)) {
Text(drug.substance)
}
}
}
}
}
}
.padding()
}
}
struct Detail: View {
let drug: Drug
var body: some View {
Text(drug.description)
}
}
I made up the model from what was available in your question.