Your First Table View (II): Behavior and Custom Cells

  • home
  • /
  • Your First Table View (II): Behavior and Custom Cells

Digital Leaves. Your First Table View (UITableView). Learn Swift and iOS Programming, easy and fun. Custom Cells.Welcome back! In this episode of “Your First Table View”, we are going to learn how to define custom cells for our table view (with a custom design) and how to add interactivity to our tables.

In the previous episode, we learned the basics of UITableView, Index Paths, Data Sources and Delegates. You might want read it first if you have never defined or worked with table views in iOS.

As always, you can get the code for this episode in my Github repository.

Our Next Steps

Once we have an initial scenario with a simple table view, we will work in two main enhancements to our user interface:

Interactive Items

At this instant, if the user clicks on the table, nothing happens. We want to show a new screen with details of the selected animal when the user selects a cell.

In order to do that, we will create a push segue and activate it when appropriate. The Delegate of the table view is the entity in charge of reacting to these interactions.

Thus, when the user selects an item in the list, the Delegate receives a call to tableView:didSelectRowAt indexPath:. Given that this method receives the Index Path, we are able to extract the element that was selected from the Data Source and act accordingly.

Custom Cells

Surely, our table view is nice, but it would be nice having a nicer design. Therefore, we are going to learn how to create a subclass of UITableViewCell to allow us to customize the appearance of the items in the table view completely.

When creating our custom cells, we will create a pair of files: a XIB file, that is a visual representation of the cell, and the .swift file, that contains the source code.

Again, this is the same concept that we saw when we learned about view controller source files and their storyboard counterparts.

Let’s start by adding interactivity to our cells.

Reacting To Cell Selection

When a cell is selected, we will store the animal that was selected and perform a segue to a new view controller. In the prepareForSegue:sender: method, we’ll pass this variable to the view controller to know which animal we need to show the details of.

First, we’ll add a new view controller in the storyboard. Then, we will add an image view for the animal, a title label and a description.

Adding Our New View Controller

For the images, I chose a free set of animal pics from Den Designs. I generated square 2x and 3x images and added them to the Assets Catalog. Then, for the descriptions, I looked for all those animals in the Wikipedia. I did copy the first paragraphs for every animal into a dictionary. The dictionary is aptly called “animalDescriptions”, and the keys for the dictionary are the names of the animals. Of course, you have all those resources currently added to the source code of the project.

Next, we’ll add the new view controller in the storyboard and configure its views. I called mine AnimalDescriptionViewController. Add a square image on top. Mine is 128×128, and sits in the center of the Y axis, 46 pixels from the top of the view. Then add a Title Label below that image. Mine is at the center of the Y axis, 24 pixels apart from the image, and uses the Hoefler Text Black, 30px font.

Finally, add a label for the Wikipedia’s description of the animal. Put it below the title label, taking the rest of space left. I did set the font to Italic Helvetica, 16px.

Add an outlet for these three elements, called respectively animalImageView, animalTitleLabel and animalDescriptionLabel. The final result should look similar to this:

Setting the Details View Controller. Your First Table View (II): Custom Cells and Adding Interactivity To Our Table View.

Besides, we will add a variable called “animalName” as an empty String. This variable will be filled with the name of the animal we need to display later.

Adding The Segue

Next step is adding the segue in the interface builder. In order to do so, hold ctrl key, click on the view controller icon for our initial view controller and drop it on the new view controller. When the dialog appears asking you the type of segue to add, choose “Show”. “Show” segues are the equivalent to the old “Push” segues, and that’s exactly what we want.

It’s always a good practice to name all your segues, and it’s essential if you want to invoke them programmatically. Let’s call this one “showAnimalDetails” (you can do this in the attributes inspector).

Configuring The Segue

Next, is time to prepare the segue, back in our initial View Controller’s source code file. First thing we need is a way of storing the animal the user selected and pass that to the details view controller. Thus, we’ll add an instance variable called selectedAnimal to contain this information.

var selectedAnimal = ""

Then, we have to make sure to set this variable in the tableView:didSelectCellAtIndex: method and call our segue.

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
   selectedAnimal = animals[indexPath.row]
   self.performSegue(withIdentifier: "showAnimalDetails", sender: nil)

In order to pass the selected animal to the new view controller, we will use the method prepareForSegue:. This function is invoked every time our current view controller is about to segue to a new view controller. Thus, we will check that we are transitioning to our destination AnimalDescriptionViewController and set its “animalName” property with the value contained in “selectedAnimal”.

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
   if let dvc = segue.destination as? AnimalDescriptionViewController {
      dvc.animalName = self.selectedAnimal

Loading The Data For The Selected Animal

There’s just one step we are missing, loading the data for the selected animal in our AnimalDescriptionViewController. A perfect place for doing that, given that we won’t be updating the information once we load it, is viewDidLoad().

override func viewDidLoad() {
   animalImageView.image = UIImage(named: animalName)
   animalNameLabel.text = animalName
   animalDescriptionLabel.text = animalDescriptions[animalName]

Then, if you run the application, you’ll be able to click on an animal and see a description alongside a beautiful image. Congratulations! You just learned how to perform a segue from a Table View item!

Now, it’s time to customize our cells’ appearance.

Custom Cells

Even though the table is looking nice, it would be nice to have a custom look for our cells. Let’s see how to completely design and add custom cells to our Table Views.

First, we will create a XIB file containing the interface design for them. This XIB file will have an associated source code file, of course, whose class inherits from UITableViewCell.

Thus, click on File > New > File (or use Cmd+N) and choose “Cocoa Touch Class”. Then, in the “Subclass of” dropdown, choose or type UITableViewCell. Finally, call our subclass “AnimalTableViewCell”. Don’t forget to check the “Also create a XIB file” box.

Pro tip: use Cmd + N to add a new file while on editing mode.

As soon as the wizard finishes, you’ll notice he has created two files: AnimalTableViewCell.xib, with the user interface, and AnimalTableViewCell.swift, with the source code. Xcode has already taken care of linking them together for you. Thus, let’s begin by editing the table view cell’s user interface.

Designing Our Custom Cells

Go to the XIB file. You’ll see an empty cell. To begin with, make the cell slightly taller (56 pixels). Then, add a UIImageView at the left, pin it to the edges at the standard distance, and add a width and height constraint of 40 pixels. Next, add a UILabel at its right. Pin it to all of its edges.

Finally, add outlets for both, called animalImageView and animalLabel respectively. You will end up with a situation like the one depicted in the figure:


Now, we just need to add a configureWith: method to set our outlets for a given animal. We will invoke this method later when configuring the cell in the Data Source’s tableView:cellForRowAtIndexPath: method.

func configureWith(animalName: String) {
   self.animalImageView.image = UIImage(named: animalName)
   self.animalLabel.text = animalName

Certainly, that was easy, wasn’t it? Now let’s add the required functionality at our View Controller to make it all work.

Configuring Our Custom Cells In Our View Controller

In the previous episode of this tutorial, we added a simple “Basic” cell to out Table View in Interface Builder. However, we don’t need that cell template anymore, so we can get rid of it. Go to the Table View in the Storyboard, click on the cell and hit delete. Make sure not to delete the whole Table View!

In order to make one of our custom cells available for the Table View, we need to register it in the View Controller, programmatically. We’ll do that in the method viewDidLoad of the view controller.

override func viewDidLoad() {
   tableView.register(UINib(nibName: "AnimalTableViewCell", bundle: nil), forCellReuseIdentifier: "AnimalTableViewCell")

the register:forCellReuseIdentifier: method loads a NIB/XIB file and assigns its cell subclass to the Table View, with a given identifier. This is roughly the same of what dragging and dropping a “Table View Cell” in Interface Builder does.

Next, we will change the code at tableView:cellForRowAtIndexPath:.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
   let cell = tableView.dequeueReusableCell(withIdentifier: "AnimalTableViewCell", for: indexPath) as! AnimalTableViewCell
   let animalName = animals[indexPath.row]
   cell.configureWith(animalName: animalName)
   return cell

First, notice how we changed the identifier we’re retrieving at dequeueReusableCell:for:. Also, we are forcing a cast down the result (which is usually returned as UITableViewCell) to AnimalTableViewCell. This will allow us to call the specific configuration method configureWithAnimalName: that we defined earlier.

Then, we just need to get the proper animal name from the array with the row of the Index Path, and configure the cell.

Polishing Touches

Your First Table View. Pull To Refresh, Cell Actions. Digital Leaves. Learn Swift and Start Building Awesome Apps.However, there’s something else we need to do. If you run the application, you will notice that our custom cells are showing, but the animal images look squashed. That’s because the default cell’s height, 44 pixels, is lower than our custom cells’ height, which is 56 pixels. There are many ways of solving this, but the easiest one is setting the height explicitly in the Delegate’s method tableView:heightForRowAtIndexPath:

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
   return 56.0

As a result, if you run the application, you’ll see our nice custom cells, with the animal pics. Nice!

Congratulations! You just learned to build custom cells and associate them to your Table Views.

Where To Go From Here

In conclusion, we greatly improved our knowledge of Table Views in this article. First, we added interactivity by making our cells selectable. Then, we learned how to design and build custom cells for a more appealing visual appearance.

Coming up next, we will learn how to allow our users to manipulate our table via editing actions, and how to implement “Pull to Refresh”. However, if you have any question or suggestion to improve this post, don’t hesitate to add a comment!