on
Registerable Views
This article was first published on Fabernovel blog.
One of the most used UI component in iOS development is UITableView
. This view is intended to present a collection of cells with a vertical layout. Its counterpart UICollectionView
does exactly the same thing for more custom layouts (grid for example).
In the following, we will call CollectionView an instance of UITableView
or UICollectionView
.
Every iOS developer knows that registering and dequeuing cells from a CollectionView is kind of a boring task. A lot of boilerplate for a simple job: tell the CollectionView which cell we want to be able to use later.
As we start to embrace Swift in our daily work at Applidium, I would like to share with you a playground I’ve been playing with recently.
This is a swifty API to register and dequeue reusable cells (think UITableViewCell
and UICollectionViewCell
).
Either a Class or a Nib
As we all know, a reusable cell is created either from a Nib or from a Class. We can represent this two cases with an enum.
Our RegisterableView
enum takes a class as associated value, to be able to provide it to the CollectionView later.
Now we can add an extension to this enum with two computed variables: nib
and cellClass
.
Last thing we need for our RegisterableView
is an identifier. Indeed we have to provide a string as identifier for each cell we register. Most of the time we use the name of the class as identifier.
First we define a protocol which returns a static identifier
And then we extend NSObject
to return the string representation of self
as identifier.
Now we can get an identifier for any NSObject
subclass. For example: UITableViewCell.identifier()
returns "UITableViewCell"
.
Finally, our RegisterableView
can return its identifier.
That’s all we need to do with RegisterableView
. Let’s now see how to register them!
A generic approach
The APIs to register cells from UITableView
and UICollectionView
are very close but not identical and we want a generic one that we can use for both.
To abstract the concrete UIKit classes, let’s create a CollectionView
protocol that can register cells, headers or footers.
We can right away add handy methods to register multiple registerable views at once.
Now that we have the generic API, the only thing that we need to do, is to make UITableView
and UICollectionView
conforms to CollectionView
. This is straightforward because most of the work is already done.
Results
With this new API, we are able to transform this ugly snippet:
to this clean and readable one:
A nice improvement based on an enum and a protocol!
Some thoughts about the dequeue
The dequeue works as usual, except that we need to use the static identifier method from ClassIdentifiable
.
We can even go one step further and clean up the dequeue a bit. The following method on UITableView
allows us to dequeue a cell for an indexPath without even specifying the identifier.
The dequeue now simply becomes:
or
The type of the cell, and thus the identifier is infered by the compiler. We do not need the identifier nor the cast at the end anymore.
Conclusion
Swift has powerful features such as enums, protocol extensions and strong type system that we can leverage to create new APIs.
You can find the full playground of RegisterableView
here.
2017-09-17 Updated for Swift 3 syntax