8 Replies
      Latest reply on Jan 15, 2020 4:52 PM by sharp11
      sharp11 Level 1 Level 1 (0 points)

        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?

        • Re: UICollectionView compositional layout with hierarchical (nested) data
          Claude31 Level 8 Level 8 (7,895 points)

          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

            • Re: UICollectionView compositional layout with hierarchical (nested) data
              sharp11 Level 1 Level 1 (0 points)

              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.

                • Re: UICollectionView compositional layout with hierarchical (nested) data
                  Claude31 Level 8 Level 8 (7,895 points)

                  Can you explain through eample what flatten mean ?

                   

                  Original data structure -> flattened.

                    • Re: UICollectionView compositional layout with hierarchical (nested) data
                      sharp11 Level 1 Level 1 (0 points)

                      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...

                        • Re: UICollectionView compositional layout with hierarchical (nested) data
                          Claude31 Level 8 Level 8 (7,895 points)

                          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

                            • Re: UICollectionView compositional layout with hierarchical (nested) data
                              sharp11 Level 1 Level 1 (0 points)

                              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 ...

                                • Re: UICollectionView compositional layout with hierarchical (nested) data
                                  Claude31 Level 8 Level 8 (7,895 points)

                                  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.

                                    • Re: UICollectionView compositional layout with hierarchical (nested) data
                                      sharp11 Level 1 Level 1 (0 points)

                                      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.