2️⃣UITableView Setup
Fall 2023 | Vin Bui
Create a Custom UITableViewCell
Creating a UITableViewCell
is very similar to how we have been creating views inside of a UIViewController
. We still define properties for the view and data, initialize those views, add them as a subview, and constrain those views. However, when working inside of a UITableViewCell
there are some slight modifications that we will need to make. Follow these steps:
Our custom class needs to be a subclass of
UITableViewCell
class CustomTableViewCell: UITableViewCell { }
Create the following initializer:
Determine what views to create and write a helper function to initialize its properties.
For example, if we need to display some text, we would create a
UILabel
and create a helper function to initialize its font, font color, etc. Note that we do not know anything about the data yet, so the property.text
of theUILabel
will not be initialized yet.
Inside of the helper function, add the views we created as a subview to
contentView
and constrain the view with respect tocontentView
. Then call the helper function inside of the initializer.This is one of the main differences from what we have been doing before. Instead of referencing
view
, we will be usingcontentView
. Note that we do not need to usesafeAreaLayoutGuide
here.
Create a
configure
function (do not makeprivate
) that will take in some data as a parameter, and configure our views.For example, we could write a function that takes in a
String
and setsUILabel.text
property equal to the value passed in.
Create a reuse identifier for this cell:
static let reuse = "<reuse_identifier>"
See “Dequeuing Cells” below for more information.
Dequeuing Cells
In Step 6 above, notice that we have a reuse identifier. First, let’s imagine we have a table view that contains a list of all students at Cornell. How many cells would we have? Thousands! Remember, each cell is a separate view and if we have thousands of views, that’s a lot of memory being used! The workaround for this would be to create only the views needed on the screen at one time. If a cell were to go off of the screen, Swift will dequeue this cell for another cell to be created. This is the reason why the cells in a UITableView
look very similar! It makes it very efficient to dequeue a cell and reuse it.
How does Swift know which cell to “pick up” and reuse? A reuse identifier is used to associate a cell that is being dequeued with another cell that is about to be rendered.
Setting Up a UITableView
A UITableView
is just like any other UIView
that we've worked with thus far. We've initialized the view by doing the following steps:
Create the view
Configure the view by changing its properties
Adding the view as a subview to some parent view
Enable auto layout and set up constraints
With a UITableView
, we do the exact same thing but with 3 additional steps:
Register a
UITableViewCell
For example, if we had a custom class called
CustomTableViewCell
with a static reuse constant calledreuse
, we would use the following code:
Set the
UITableView
delegate (create an extension just like any other protocol)See UITableViewDelegate section below
Set the
UITableView
dataSource (create an extension just like any other protocol)See UITableViewDataSource section below
6: UITableViewDelegate
The purpose of a UITableViewDelegate
is to add functionality to the table view. A class conforming to the protocol UITableViewDelegate
does not have any required functions to implement; however, the two most common functions to implement are: heightForRowAt
and didSelectRowAt
.
Tip: If we start typing heightForRowAt
or didSelectRowAt
, Xcode will autofill the function header for us!
7: UITableViewDataSource
In contrast to UITableViewDelegate
, there are two required functions to implement: cellForRowAt
and numberOfRowsInSection
.
For numberOfRowsInSection
, we want to provide the number of rows (cells) for a section. Usually, this is the size of our data model array. For example, if our table view listed out all students at Cornell, we would have a data model representing an array of Student objects. The number of rows would be the size of the array (use .count
to get the size).
The purpose of cellForRowAt
is to determine the cell class to use (in addition to registering the cell) as well as configuring the cell (by calling the configure
function). The following code is for a custom cell class called CustomTableViewCell
:
Let’s go over this function line by line:
First, we dequeue the cell with the given reuse identifier. This gives us a
UITableViewCell
. Now, we need to cast it to our custom type by using theas?
keyword. This returns an optional type of our custom cell. We unwrap it by using aguard let
(or we could use anif let
). If the casting failed and the optional holdsnil
, we return a basicUITableViewCell
.Then, we need to identify which data this cell will hold. Most of the time, we will have some data model array (such as an array of students). To determine the position a cell is located inside of a table view, we use
indexPath.row
which returns anInt
. We could then use this value to access an element inside of our data model array.Next, we would need to configure our cell with the data model that we retrieve in Step 2. We can pass this information into our custom cell class’s
configure
function that we implemented earlier to configure the cell’s views such as changing a UILabel’s text.Finally, we return the configured custom cell.
Complete Code
Last updated