LUExpandableTableView
A subclass of UITableView
with expandable and collapsible sections
Preview
Installation
CocoaPods
CocoaPods is a dependency manager for Cocoa projects. You can install it with the following command:
$ sudo gem install cocoapods
CocoaPods 1.7.0+ is required.
To integrate LUExpandableTableView
into your Xcode project using CocoaPods, specify it in your Podfile
:
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '9.0'
use_frameworks!
target '<Your Target Name>' do
pod 'LUExpandableTableView'
end
Then, run the following command:
$ pod install
Carthage
You can use Carthage to install LUExpandableTableView
by adding it to your Cartfile
:
github "LaurentiuUngur/LUExpandableTableView" ~> 5.0
Then run carthage update
.
If this is your first time using Carthage in the project, you'll need to go through some additional steps as explained over at Carthage.
Swift Package Manager
To integrate using Apple's Swift Package Manager, add the following as a dependency to your Package.swift
:
.Package(url: "https://githubLaurentiuUngur/LUExpandableTableView", majorVersion: 5)
Here's an example of PackageDescription
:
import PackageDescription
let package = Package(name: "MyApp",
dependencies: [
.Package(url: "https://github.com/LaurentiuUngur/LUExpandableTableView", majorVersion: 5)
])
Manually
If you prefer not to use either of the before mentioned dependency managers, you can integrate LUExpandableTableView
into your project manually.
Usage
- Import
LUExpandableTableView
into your project.
import LUExpandableTableView
- Register a cell for an instance of
LUExpandableTableView
. Registered class must be a subclass ofUITableViewCell
. This step is not be necessary if you use storyboard.
expandableTableView.register(MyTableViewCell.self, forCellReuseIdentifier: cellReuseIdentifier)
- Register a header for an instance of
LUExpandableTableView
. Registered class must be a subclass ofLUExpandableTableViewSectionHeader
Keep in mind that you cannot use storyboard in order to do this.
expandableTableView.register(UINib(nibName: "MyExpandableTableViewSectionHeader", bundle: Bundle.main), forHeaderFooterViewReuseIdentifier: sectionHeaderReuseIdentifier)
- Set as data source and delegate.
expandableTableView.expandableTableViewDataSource = self
expandableTableView.expandableTableViewDelegate = self
- Implement
LUExpandableTableViewDataSource
andLUExpandableTableViewDelegate
protocols.
// MARK: - LUExpandableTableViewDataSource
extension ViewController: LUExpandableTableViewDataSource {
func numberOfSections(in expandableTableView: LUExpandableTableView) -> Int {
return 42
}
func expandableTableView(_ expandableTableView: LUExpandableTableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func expandableTableView(_ expandableTableView: LUExpandableTableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = expandableTableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as? MyTableViewCell else {
assertionFailure("Cell shouldn't be nil")
return UITableViewCell()
}
cell.label.text = "Cell at row \(indexPath.row) section \(indexPath.section)"
return cell
}
func expandableTableView(_ expandableTableView: LUExpandableTableView, sectionHeaderOfSection section: Int) -> LUExpandableTableViewSectionHeader {
guard let sectionHeader = expandableTableView.dequeueReusableHeaderFooterView(withIdentifier: sectionHeaderReuseIdentifier) as? MyExpandableTableViewSectionHeader else {
assertionFailure("Section header shouldn't be nil")
return LUExpandableTableViewSectionHeader()
}
sectionHeader.label.text = "Section \(section)"
return sectionHeader
}
}
// MARK: - LUExpandableTableViewDelegate
extension ViewController: LUExpandableTableViewDelegate {
func expandableTableView(_ expandableTableView: LUExpandableTableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
/// Returning `UITableViewAutomaticDimension` value on iOS 9 will cause reloading all cells due to an iOS 9 bug with automatic dimensions
return 50
}
func expandableTableView(_ expandableTableView: LUExpandableTableView, heightForHeaderInSection section: Int) -> CGFloat {
/// Returning `UITableViewAutomaticDimension` value on iOS 9 will cause reloading all cells due to an iOS 9 bug with automatic dimensions
return 69
}
// MARK: - Optional
func expandableTableView(_ expandableTableView: LUExpandableTableView, didSelectRowAt indexPath: IndexPath) {
print("Did select cell at section \(indexPath.section) row \(indexPath.row)")
}
func expandableTableView(_ expandableTableView: LUExpandableTableView, didSelectSectionHeader sectionHeader: LUExpandableTableViewSectionHeader, atSection section: Int) {
print("Did select cection header at section \(section)")
}
func expandableTableView(_ expandableTableView: LUExpandableTableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
print("Will display cell at section \(indexPath.section) row \(indexPath.row)")
}
func expandableTableView(_ expandableTableView: LUExpandableTableView, willDisplaySectionHeader sectionHeader: LUExpandableTableViewSectionHeader, forSection section: Int) {
print("Will display section header for section \(section)")
}
}
For more usage details please see example app
Issues
- Returning
UITableViewAutomaticDimension
value on iOS 9 will cause reloading all cells due to an iOS 9 bug with automatic dimensions. On iOS 10 it works fine.
Requirements
- Xcode 10.2+
- Swift 5.0+
- iOS 9.0+
Author
License
- LUExpandableTableView is available under the MIT license.