How to Programmatically Remove a Cell From a Static UITableView

There are two different ways to add cells to a UITableView.

The first is by using dynamic prototype cells in your table view. For a dynamic table view, you programmatically arrange the cells and sections of the table view by implementing the UITableViewDataSource protocol in code. Using this method, you can display a variable number of cells and sections at runtime.

The second method is by using a static layout. With this approach, you lay out the cells and sections using the storyboard, and there’s no need to write any code. Once you lay out the storyboard, the cells and sections are fixed.

Which method is best? That depends. Dynamic table views are generally used to display data. You will not know how many cells to display in the table view until you query your database or request data from an API. On the other hand, static table views are generally used for UI control flow that does not change at runtime.

There is no reason you couldn’t use a dynamic table view for every purpose, but that would require writing code for every table view. With a static table view, there’s little to no code to write, and your UI control flow is documented in the storyboard for developers to understand.

The Problem

Let’s say I have to show a cell based on some business logic–maybe that cell should only be visible to admin users and hidden for everyone else. If I know ahead of time that I have to hide/show several different cells on a table view at runtime, then I would use dynamic prototypes from the beginning. If, however, I only have one or two cells that I need to hide/show at runtime, then I will use the method I am about to show you and keep the table view as static.

Removing the Last Cell

I have laid out a static table view with three cells.
A storyboard containing a table view with three cells

When I run, I get the following table view:

A table view with three cells

The task of removing the last cell at runtime is pretty easy. Even though we do not have to implement the UITableViewDataSource protocol for static cells, implementing certain functions in the protocol will allow us to remove the cells we want. To remove the last cell in the table view, all we need to do is override the function that tells the table view how many cells there are.

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    let count = super.tableView(tableView, numberOfRowsInSection: section)
    let userIsAnAdmin = false
    if !userIsAnAdmin {
        // remove the last cell
        return count - 1
    }
    return count
}

In this code snippet, the first thing I do is ask the table view how many cells there are based on the static layout in the storyboard. For demonstration purposes, I hard coded a variable called userIsAnAdmin to be false so I could demonstrate how the last cell is removed when you reduce the count by one.

table view with last cell removed
If you have sections in your static table view, all you need to do is reduce the count of the cells in that section. The other section counts remain untouched.

Removing a Different Cell

It was easy to remove the last cell because all I needed to do was return a different number of cells. To remove a different cell, I have to implement another function in the UITableViewDataSource. The function to override is the one that supplies the cell for a given index path.

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    let count = super.tableView(tableView, numberOfRowsInSection: section)
    if !userIsAnAdmin {
        // remove the second cell
        return count - 1
    }
    return count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if !userIsAnAdmin && indexPath.row > 0 {
        // remove the second cell by skipping it and returning the third cell in its place
        return super.tableView(tableView, cellForRowAt: IndexPath(row: indexPath.row + 1, section: 0))
    }
    return super.tableView(tableView, cellForRowAt: indexPath)
}

The first function is the same as before. If I want to remove the second cell, all I do is return a count that is one less than the total.

The next step is to override the cellForRowAt function. When the function is called for the first cell, it behaves as normal. If the row is greater than the first cell, then skip over the second cell and return the subsequent cells in the table view.

table view with second row removed
As you can imagine, this can get out of hand if you have several cells that are toggled on/off in this way. When the code gets too complex, I recommend refactoring your static table view to use dynamic cells instead.