Photo by Mika Baumeister on Unsplash

Compositional SwiftUI List

James Rochabrun
Geek Culture
Published in
3 min readJan 27, 2021

--

In this post, I want to share with you an example of how to mix UIKit and SwiftUI in your projects. For that, I created a small library called CompositionalList. 🧩

CompositionalList is a SwiftUI UIViewControllerRepresentablewrapper powered by UIKit DiffableDataSourceand Compositional Layout. 🥸
It is customizable and flexible, supports multiple sections, cell selection, and can be used in UIKit using a UIHostingController or in a SwiftUI app.

You can add it to your project directly adding it as a swift package in Xcode: Click File -> Swift Packages -> Add Package Dependency and add this URL.

For this example, we are going to use the RSS Itunes Feed generator to display the Apple Music feed like this…

https://github.com/jamesrochabrun/CompositionalList/tree/main/Example/CompositionalListExample

The Itunes Feed API is awesome but sadly does not return sectioned data, so I had to chunk the results for the purposes of this example. All the chunk code, networking layer, custom compositional layouts and theObservableObject model that publishes the results can be found here.

We will just focus on how to display the results in our CompositionalList

Apple Music Feed in a Compositional List.

Let’s go step by step…

Don’t forget to import CompositionalList 😬

  1. Customizing the items per row, this closure provides a model and an indexpath and expects a View as the return value. Here you can return different SwiftUI views for each section. If you use a conditional statement like a Switch, in this case, you must use a Group as the return value. For example in this case the compiler will infer this as the return value:
Group<_ConditionalContent<_ConditionalContent<TileInfo, ListItem>, ArtWork>>

2. Customizing the header or footer per section, this closure provides the section identifier, the indexPath for the corresponding section, and the kind which can be UICollectionView.elementKindSectionHeader or UICollectionView.elementKindSectionFooter (this will be defined by your layout). It expects a View as a return value, you can customize your return value based on the section or if it's a header or a footer. Same as point number 1, if a conditional statement is used make sure to wrap it in a Group.

The SwiftUI views returned for headers or footers will dynamically adapt its content, you can return from a Text and even a whole new horizontal List!

Implementing this closure is required even If you don’t define headers or footers in your layout you still need to return a View. In that case, you can return a Spacer with a height of 0. (looking for a more elegant solution by now 🤷🏽‍♂️).

3. SelectionProvider a closure that internally uses UICollectionViewDelegate cell did select method to provide the selected item, implementing this closure is optional.

4. customLayout environment object, here you can return any kind of layout as long is a UICollectionViewLayout. This library also contains some defined NSCollectionLayouSection extension methods that you can use to compose your layouts, the definition of .composed() can be found here.

5. Something that keeps me scratching my head is that we need to use a conditional statement verifying that the array is not empty in order for this to work. However, This is handy for this case because we can handle loading or error state here. 😬

And that is it, mixing UIKit tools with SwiftUI is very well supported and let you unblock certain limitations that you can currently find in the SwiftUI framework.

The full repo is available and open-source here.

--

--