let frc = NSFetchedResultsController(
fetchRequest: alertsFetchRequest,
managedObjectContext: self.moc,
sectionNameKeyPath: "formattedDateDue",
cacheName: nil)
How can I expand and collapse the sections on my table view when I've used the NSFetchedResultsController to section my records?
I have seen a lot of tutorials that explain expanding and collapsing cells themselves but not anything on sections produced using the fetched results controller.
First, you need an array to keep track of whether each section is expanded or collapsed:
var sectionExpandedInfo : [Bool] = []
After the fetched results controller has done its initial performFetch
, populate this array with true
for each section (assuming you want sections expanded by default):
sectionExpandedInfo = []
for _ in frc.sections! {
sectionExpandedInfo.append(true)
}
Amend the numberOfRowsInSection
method to return zero if the section is collapsed:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if sectionExpandedInfo[section] { // expanded
let sectionInfo = self.frc.sections![section]
return sectionInfo.numberOfObjects
} else { // collapsed
return 0
}
}
To toggle whether a section is expanded or not, I've used a button as the viewForHeaderInSection
, with the section name as the title:
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if (self.frc.sections!.count > 0) {
let sectionInfo = self.frc.sections![section]
let sectionHeaderButton = UIButton(type: .Custom)
sectionHeaderButton.backgroundColor = UIColor.redColor()
sectionHeaderButton.setTitle(sectionInfo.name, forState: .Normal)
sectionHeaderButton.addTarget(self, action: #selector(MasterViewController.toggleSection(_:)), forControlEvents: .TouchUpInside)
return sectionHeaderButton
} else {
return nil
}
}
and in the toggleSection
method I then use the title to determine which header button has been tapped, and expand/collapse the corresponding section:
func toggleSection(sender: UIButton) {
for (index, frcSection) in self.frc.sections!.enumerate() {
if sender.titleForState(.Normal) == frcSection.name {
sectionExpandedInfo[index] = !sectionExpandedInfo[index]
self.tableView.reloadSections(NSIndexSet(index: index), withRowAnimation: .Automatic)
}
}
}
If your FRC inserts or deletes sections, you need to update the sectionExpandedInfo
array to include/remove the extra section:
func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
switch type {
case .Insert:
self.sectionExpandedInfo.insert(true, atIndex: sectionIndex)
self.tableView.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade)
case .Delete:
self.sectionExpandedInfo.removeAtIndex(sectionIndex)
self.tableView.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade)
default:
return
}
}
Again this assumes you want sections expanded by default.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With