UICollectionView compositional layout with hierarchical (nested) data

I am super excited about the new compositional layout apis in collection view, however it's not clear how to handle an important use case in my app: hierarchical data.


Here's a made-up example of a hierarchical data model:


I'm displaying a list of fruit. For each type of fruit (apple, banana, ...), I have:

+ a variable number of varieties

+ a variable number of favorite dishes


In my list, I want each variety and each dish to have its own thumbnail image.


From a layout perspective, compositional layout is perfect for this; but from a data model perspective ...


Each fruit could be a separate section; but within each section you have to flatten your data, indexing varieties and dishes in a single collection. That feels ugly and error-prone.


Now imagine we want a single list that covers fruit, vegetables, and herbs. If we make each main category a section, then within each category we have to flatten all our names, varieties and dishes into one big list. That feels really ugly and error-prone.


Alternatively, we could define a separate section for every distinct data set:


1. Apple

2. Apple varieties

3. Apple dishes

4. Banana

5. Banana varieties

6. Banana dishes

...


But this also loses the nested quality of the data. Eg., we couldn't have separate sections for our categories.


I'm wondering if I'm thinking about this correctly or perhaps missing something?

Replies

How would you want your data be presented ?


Seems you have set to have one section per fruit. Seems logical.


Then, how do you want in each section ?

group varieties and group receipes ?


I woul use group structure there.


Have a look here to see how to achieve this:

h ttps://hackernoon.com/complex-collection-view-layouts-in-swift-with-compositional-layout-z0bmk35kw

Thanks @Claude31. Yes, I would use groups for varieties and dishes. But I don't think you understood my question. The groups only handle layout. The issue is having to flatten the data source bc index path only has section + item.

Can you explain through eample what flatten mean ?


Original data structure -> flattened.

If we let each fruit be its own section, and look at it through the lens of IndexPath:


Number of sections: fruitArray.count

Number of rows (items) in "apple" section: appleVarieties.count + appleDishes.count


The flattening is that we had to treat varieties and dishes as if in same array.


But maybe my problem is just that I'm still thinking in terms of IndexPath and now diffable data sources are organized in terms of identifiers. I need to play with that some more and maybe this whole issue goes away...

I've not looked at the diffable option.


Assuming your data model is


struct Fruit {
     var name: String // "apple"
     var varieties : [String]     // ["mcintosh", "golden", "gala", "granny smith"…]
     var receipies : [String]     // ["apple pie", "tatin", …]
}



You could define:


enum TypeKey {
    case v
    case r
}
   
// then you could create a dictionary of dictionaries for your dataSource

var allFruits : [String: [TypeKey: [String]] ] = [
    "apple": [.v: ["mcintosh", "golden", "gala", "granny smith"],
              .r: ["apple pie", "tatin", "compote"]],
    "orange": [.v: ["seville soar", "tangerine", "cara cara", "mandarin"],
               .r: ["orange cake", "salad", "marmelade"]]
]


Now you can use allFruits["apple"] in first section and get varieties and receipes.


And create a dictionary to hold the names of all images to call in UIImage(named: someName)


Is it what you are looking for ?

Number of sections: fruitArray.count allFruits.count

Number of rows (items) in "apple" section: appleVarieties.count + appleDishes.count

allFruits["apple"]![.v]!.count + allFruits["apple"]![.r]!.count

or

appleVarieties = allFruits["apple"]![.v]!

appleDishes = allFruits["apple"]![.r]!


The flattening is that we had to treat varieties and dishes as if in same array. Done

I must not be explaining myself very well... it's not that I can't manage my array indexes. Anyway, thank you so much for trying! I'm going to play with this some more ...

Well, it's you or me, but effectively I do not understand where your problem is.


You said: The flattening is that we had to treat varieties and dishes as if in same array.


Could you elaborate how you would like to use this flattening, even if it is not real code.

If I were coding this the "usual" way, I would design a cell that had a title label and then had subviews that could contain variable numbers of images for varieties and dishes. When I designed my data source, it would have a single section; and one row for each type of fruit. And each type of fruit would map onto a single cell.


But this new compositional layout approach is totally different. To take advantage of this, I can't design a single cell that will handle a fruit type. Instead, I'll have a cell that shows the title ("Apple", "Orange", etc.); a different cell type to handle a single variety (laid out in a group, with line-wrapping); and maybe another cell type to handle a single dish (laid out in another group).


So I have three cell types, and I have to flatten all my data into one set of rows.


After playing with this a bit, I realize that identifiers come to the rescue, you don't have to fuss with index path at all. But it still feels pretty odd.