UITableView with Collapsible (expand and collapse) Cells

Healthy lifestyle: Importance and Approach

UITableView with Collapsible (expand and collapse) Cells

Table view cells should expand and shrink when clicked is a common use case.

Let's create a TableViewController with custom cells. Cells can be configured in three views:

  1. Cell View: Displays the contents of the cell in the default mode.
  2. Expanded View (Detailed View): Displays the contents of the cell in expanded mode.
  3. A container view (UIStackView) containing cells anddetailed views.

So CustomCell looks like this:

 import UIKit
	final class CustomTableViewCell: UITableViewCell {
	    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
	        super.init(style: style, reuseIdentifier: reuseIdentifier)
	    required init?(coder: NSCoder) {
	        fatalError("init(coder:) has not been implemented")
	    private let containerView = UIStackView()
	    private let cellView = CustomTableCellView()
	    private let detailView = CustomTableDetailView()
	    func setUI(with index: Int) {
	        cellView.setUI(with: Constants.fruits[index])
	        detailView.setUI(with: index, image: UIImage(named: Constants.fruits[index]) ?? UIImage())
	    func commonInit() {
	        selectionStyle = .none
	        detailView.isHidden = true

	        containerView.axis = .vertical

	        containerView.translatesAutoresizingMaskIntoConstraints = false
	        cellView.translatesAutoresizingMaskIntoConstraints = false
	        detailView.translatesAutoresizingMaskIntoConstraints = false
	        containerView.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor).isActive = true
	        containerView.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor).isActive = true       
	        containerView.topAnchor.constraint(equalTo: self.contentView.topAnchor).isActive = true
	        containerView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor).isActive = true


Now let's register this unit in the controller and add the required methods:

    import UIKit
        final class HomeTableViewController: UITableViewController {
            override func viewDidLoad() {
            guard let cell = tableView.dequeueReusableCell(
                        withIdentifier: "CustomTableViewCell") as? CustomTableViewCell
                else { return UITableViewCell() }
                cell.setUI(with: indexPath.row)
                return cell


Now that our table view and custom cell with two views (folded view and expanded view) are ready, now we need to add settings to show and hide the detail view when the cell is touched.

    extension CustomTableViewCell {
          var isDetailViewHidden: Bool{
            return detailView.isHidden
          func showDetailView(){
            detailView.isHidden = false
          func hideDetailView(){
            detailView.isHidden = true
          override func setSelected(_ selected: Bool, animated: Bool) {
            super.setSelected(selected, animated: animated)
            if isDetailViewHidden , selected {
            }else {

We use the setSelected method of tableViewCell here, so when the cell is selected, it will display detailView, when it is not selected, it will be hidden.

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
            UIView.animate(withDuration: 0.3){

Now in order to make the expansion and collapse animation go smoothly, UITableView is helping to use a great API called:


This API is available since iOS 11+. This method animates a collection of insert, delete, reload, and move actions. This can happen without charging the battery. The same effect can be achieved using `beginUpdates()` and `endUpdates()`, but Apple recommends that we should use `performBatchUpdates` instead. We can now call this method with an animation block to get a smoother selection of cells The effect, like

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
          if let cell = self.tableView.cellForRow(at: indexPath) as? CustomTableViewCell {

, if we need to hide the detailView when selecting another cell, we can use to easily achieve.

I Hope you enjoy this blog

Thank You

Want a Team that Delivers Result ? Connect now with us.

Our Offices


F-429, Phase 8B, Industrial Area, SAS Nagar, Punjab 160059

+91 82198-18163


13506 Summerport Village Pky Suite 355 Windermere, FL 34786

+1 (321) 900-0079


15 Meltwater Cres, Brampton L6P3V8

+1 (647) 892-6147