How to use Dicitonary in SwiftUI ForEach to make a List

How can i use a dictionary of type [SomeObject : [ValueObjects]]that belongs to viewModel(ObservableObject) to make a SwiftUI List using ForEach?
Answered by DelawareMathGuy in 622355022
hi,

OOPer's request for specificity is important: unless you know what a List/ForEach structure will display in each row, you won't know what type of Array you would need to drive the display.

suppose, even, that you want a sectioned list using a List/ForEach/Section/ForEach construct, where each section corresponds to a SomeObject, and the rows of the section correspond to the ValueObjects associated with that SomeObject in the dictionary.

if you'd like to have the latter, sectioned-list setup, then it would be nice to have an array where each element is basically a SomeObject and [ValueObject] pair. that's not really that hard to do: something like this would work:

Code Block
// a new struct to represent a key-value pairing in your dictionary
struct ListItem {
let someObject: SomeObject
let valueObjects: [ValueObject]
}
// make an array of ListItem structs, one for each item in the dictionary
// assumes that SomeObject is Hashable and Comparable
var myList = [ListItem]()
for key in myDictionary.keys.sorted() {
myList.append(ListItem(someObject: key, valueObjects: myDictionary[key]!))
}

i don't know what your object types actually are, but if SomeObject had a name (String) variable, and ValueObject had a value (Int) variable, then this is how you read what myList in the code above gives you:
Code Block
for listItem in myList {
print(listItem.someObject.name)
for valueObject in listItem.valueObjects {
print(valueObject.value)
}
}

so this would match up with a sectioned list where you would use List/ForEach/Section/ForEach. indeed, it would look something like this:
Code Block
List {
ForEach(myList, id: \.self) { listItem in
Section(header: Text(listItem.someObject.name)) {
ForEach(listItem.valueObjects, id: \.self) { valueObject in
// show data for the valueObject
}
}
}
}

although you'd have to be sure that ListItem is Hashable (it would be if both SomeObject and ValueObject were hashable).

hope that helps,
DMG
Please be more specific. What sort of data does your Dictionary have? What does each row of your List use? How is SomeObject defined?
Accepted Answer
hi,

OOPer's request for specificity is important: unless you know what a List/ForEach structure will display in each row, you won't know what type of Array you would need to drive the display.

suppose, even, that you want a sectioned list using a List/ForEach/Section/ForEach construct, where each section corresponds to a SomeObject, and the rows of the section correspond to the ValueObjects associated with that SomeObject in the dictionary.

if you'd like to have the latter, sectioned-list setup, then it would be nice to have an array where each element is basically a SomeObject and [ValueObject] pair. that's not really that hard to do: something like this would work:

Code Block
// a new struct to represent a key-value pairing in your dictionary
struct ListItem {
let someObject: SomeObject
let valueObjects: [ValueObject]
}
// make an array of ListItem structs, one for each item in the dictionary
// assumes that SomeObject is Hashable and Comparable
var myList = [ListItem]()
for key in myDictionary.keys.sorted() {
myList.append(ListItem(someObject: key, valueObjects: myDictionary[key]!))
}

i don't know what your object types actually are, but if SomeObject had a name (String) variable, and ValueObject had a value (Int) variable, then this is how you read what myList in the code above gives you:
Code Block
for listItem in myList {
print(listItem.someObject.name)
for valueObject in listItem.valueObjects {
print(valueObject.value)
}
}

so this would match up with a sectioned list where you would use List/ForEach/Section/ForEach. indeed, it would look something like this:
Code Block
List {
ForEach(myList, id: \.self) { listItem in
Section(header: Text(listItem.someObject.name)) {
ForEach(listItem.valueObjects, id: \.self) { valueObject in
// show data for the valueObject
}
}
}
}

although you'd have to be sure that ListItem is Hashable (it would be if both SomeObject and ValueObject were hashable).

hope that helps,
DMG
How to use Dicitonary in SwiftUI ForEach to make a List
 
 
Q