Expand/collapse section in UITableView in iOS
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
Implementing expand/collapse sections in a UITableView involves toggling the number of rows in each section based on a collapsed/expanded state. When a section header is tapped, you update the state and call tableView.reloadSections() to animate the rows appearing or disappearing. The key data structure is an array of section models, each tracking its title, items, and whether it is currently expanded.
Data Model
Each section tracks its own isExpanded state. When collapsed, the section shows zero rows. When expanded, it shows all its items.
UITableView Data Source
The critical line is numberOfRowsInSection — returning 0 when isExpanded is false hides all rows in that section.
Section Header with Tap Gesture
The tag property stores the section index on the header view. When tapped, isExpanded is toggled and reloadSections animates the change.
Using a Custom Header Cell
Using UITableViewHeaderFooterView with dequeueReusableHeaderFooterView is more efficient than creating new views each time, especially with many sections.
Animated Arrow Rotation
Common Pitfalls
- Using
reloadData()instead ofreloadSections(): CallingreloadData()refreshes the entire table without animation. UsereloadSections(_:with:)with.automaticto get smooth expand/collapse animations for the specific section. - Forgetting to return 0 rows for collapsed sections: If
numberOfRowsInSectionalways returns the item count regardless of state, the section never visually collapses. The row count must be 0 whenisExpandedis false. - Using cell
tagfor section identification in reusable headers: Thetagapproach works for simple cases, but reused header views may retain stale tags. Using a closure callback (onTap) or storing the section index in a custom property is more reliable. - Not handling estimated row heights: When using self-sizing cells with
UITableView.automaticDimension, failing to setestimatedRowHeightcauses jump artifacts during expand/collapse animations. Set a reasonable estimate to smooth transitions. - Modifying
sectionsarray off the main thread: UITableView updates must happen on the main thread. TogglingisExpandedand callingreloadSectionsfrom a background thread causes crashes or visual corruption.
Summary
- Track
isExpandedstate per section in your data model - Return 0 from
numberOfRowsInSectionwhen a section is collapsed - Use
reloadSections(_:with: .automatic)for animated expand/collapse - Add a tap gesture to section headers that toggles
isExpandedand reloads the section - Use
UITableViewHeaderFooterViewwith dequeue for efficient header reuse - Consider using
UIImageViewwith rotation transforms for animated arrow indicators
Related reading
- Explaining difference between automaticallyAdjustsScrollViewInsets, extendedLayoutIncludesOpaqueBars, edgesForExtendedLayout in iOS7
- ''Expressions are not allowed at the top level'' if the module is not main.swift
- Extra padding above table view headers in iOS 15
- Facebook SDK app not registered as a URL Scheme
- Fade/dissolve when changing UIImageView's image
- Fade/dissolve when changing UIImageView's image
- Failed to find or create execution context for description IBCocoaTouchPlatformToolDescription 0x7fa8bad9a6f0
- Failed to install android-sdk java.lang.NoClassDefFoundError javax/xml/bind/annotation/XmlSchema
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.