Build an iOS 16 UICollectionView With a SwiftUI View as the Cell | by PTeng | Jun, 2022

Leverage the UIHostingConfiguration

This post will try to illustrate how to incorporate a SwiftUI view inside a UICollectionView , alongside it will provide a quick introduction to using modern collection views and diffable data sources.

It will utilize the new UIHostingConfiguration API that has been introduced for iOS and tvOS 16 in WWDC 22. You will need Xcode 14 (beta as of this writing) if you wanted to try this.

We will create a very minimal ToDo List screen that will display the list of ToDo list items and their state. The ToDo list will be a collection view and its cells will be composed as a SwiftUI view.

When we complete the screen will look like the below. A complete example of what is being discussed below can be found here.

A Todo list
UICollectionView ToDo list with SwiftUI views

This follows a previous post about using a SwiftUI view inside a UIKit view.

A ToDoListdata structure consists of an array of ToDoListItems. This relationship is modeled as shown below. The Todo list data we have will have ToDo lists for Home and Office.

Let’s create a SwiftUI view that will display an individual ToDoListItem as below.

The view above uses another SwiftUI view, TaskStatus. It displays the status of the ToDo list item (completed or pending) as a system Image icon depending on the status.

We will create a UIViewController class called ToDoListViewController. In the viewDidLoad method of the class we will do the following.

  • Create and setup the collection view using a compositional layout (see discussion in next section) and insert it as a subview.
  • Set the collection view diffable data source and connect it to the collection view. This will also set it up to use the SwiftUI view.
  • apply data to the diffable data source using snapshot

We will discuss the working of functions in viewDidLoad , the collection view layout and datasource in the rest of the post below.

Collection views are initialized using a UICollectionViewLayout property. This defines how the cells are laid out in a collection view. Since iOS 13 we have been provided with a new layout API called UICollectionViewCompositionalLayout , as Apple puts it “A layout object that lets you combine items in highly adaptive and flexible visual arrangements”. This layout also introduced the concept of Section, Group & Item.

Sections have Groups inside them, and Groups have items in them. In our case the section corresponds to either Home or Office and the item is an individual ToDoList item.

In our example a ToDo list we will span the item across the whole width of the screen ( fractionalWidth(1.0) ) and sets it height to be the height of the group it’s in ( fractionalHeight(1.0) ).

Similarly, we want the section to span the whole width & have an absolute height of 60 ( absolute(60) ).

Diffable data source and Cell registration

Since iOS 13 and tvOS 13, we have the API for UICollectionViewDiffableDataSource which has greatly simplified how collection views source their data.

We use it to connect a collection view to its data source and define its “cell provider”. A cell provider is a function that returns a cell for a collection view. Its init signature is init(collectionView:cellProvider:) .

Alongside the diffable data source we also have an API to do a “cell registration” (also achievable using older APIs such as register(_:forCellWithReuseIdentifier:)). The cell registration API offers a way to configure a cell for display.

Now the power of cell registration in terms of SwiftUI comes when we use it to set the cells contentConfiguration property. We use it to supply the UIHostingConfiguration which is a new API (iOS 16) that allows us to specify a SwiftUI view as its content. As we see above we have set the content to CellView(toDoListItem: item) , where CellView is a SwiftUI view we created earlier.

Following this, we use the dequeConfiguredCell(using:for:item) API

UICollectionViewDiffableDataSource components

To complete the data source we finally set the supplementaryViewProvider property of the data source to return a regular UIKit view HeaderViewCell .

The last step to bring the collection view to life is to apply some data into it. Again this is done using a recent API (iOS 13) called NSDiffableDataSourceSnapshot .

A diffable data source utilizes the concept of Section and Item that we discussed before. We initialize a diffable data source object using a SectionIdentifierType ToDoListItemType and a ItemIdentifierType ToDoListItem.

Our ToDo list items belong to either the “Home” or “Office” section. We use the applySections and appendItems API followed by the apply API on the datasource to set the data.

When we apply a snapshot to the collection view datasource the collection view automatically reloads the data !

Collection views have improved quite a lot in terms of their developer experience since iOS 13 with the introduction of Compositional layout and diffable data sources. Along with the ever-improving support and improvements with SwiftUI, we are now able to leverage the benefits in existing collectionView.

The main concepts to grasp when working with these components is the understanding of DiffableDataSource, Compositional layouts and Cell registration.

A complete example of an Xcode project can be found here.

News Credit

%d bloggers like this: