[英]Expand/collapse UITableView sections with a backing NSFetchedResultsController
let frc = NSFetchedResultsController(
fetchRequest: alertsFetchRequest,
managedObjectContext: self.moc,
sectionNameKeyPath: "formattedDateDue",
cacheName: nil)
当我使用NSFetchedResultsController来记录我的记录时,如何展开和折叠表视图中的部分?
我已经看到很多教程解释了扩展和折叠单元格本身,但没有解释使用获取结果控制器生成的部分。
首先,您需要一个数组来跟踪每个部分是展开还是折叠:
var sectionExpandedInfo : [Bool] = []
在获取结果控制器完成其初始performFetch
,为每个部分填充此数组为true
(假设您希望默认情况下展开部分):
sectionExpandedInfo = []
for _ in frc.sections! {
sectionExpandedInfo.append(true)
}
如果折叠部分,修改numberOfRowsInSection
方法以返回零:
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
}
}
要切换是否扩展了一个部分,我使用了一个按钮作为viewForHeaderInSection
,并将部分名称作为标题:
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
}
}
然后在toggleSection
方法中我使用标题来确定已经点击了哪个标题按钮,并展开/折叠相应的部分:
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)
}
}
}
如果您的FRC插入或删除部分,您需要更新sectionExpandedInfo
数组以包含/删除额外部分:
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
}
}
同样,这假设您希望默认情况下展开部分。
如果要更改结果集,则需要更改请求中的谓词并再次调用performFetch()
。 然后,您可以更新您的表格。 但是,这可能会导致性能问题。 您可以考虑使用其他更复杂的技术来管理模型视图绑定,例如为每个扩展的部分设置不同的获取结果控制器。 当用户展开一个部分时,创建一个新的获取结果控制器,只获取该部分的对象并更新表视图。 当用户折叠该部分时,丢弃获取结果控制器。 但是,这可能会使表视图数据源实现变得相当复杂。
这里是Swift 4版本的pbasdf很棒的解决方案:
定义和填充布尔数组:
sectionExpandedInfo = []
for _ in _fetchedResultsController!.sections! {
sectionExpandedInfo.append(true)
}
numberOfRowsInSection
方法:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if sectionExpandedInfo[section] { // expanded
let sectionInfo = self.fetchedResultsController.sections![section] as NSFetchedResultsSectionInfo
return sectionInfo.numberOfObjects
} else { // collapsed
return 0
}
}
在节标题中定义按钮(我必须将toggleSelection
参数_:
替换为sender:
为了使它适用于我:
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if (self.fetchedResultsController.sections!.count > 0) {
let sectionInfo = self.fetchedResultsController.sections![section]
let sectionHeaderButton = UIButton(type: .custom)
sectionHeaderButton.backgroundColor = UIColor.red
sectionHeaderButton.setTitle(sectionInfo.name, for: [])
sectionHeaderButton.addTarget(self, action: #selector(MasterViewController.toggleSection(sender:)), for: .touchUpInside)
return sectionHeaderButton
} else {
return nil
}
}
toggleSection
函数:
@objc func toggleSection(sender: UIButton) {
for (index, frcSection) in self.fetchedResultsController.sections!.enumerated() {
if sender.title(for: []) == frcSection.name {
sectionExpandedInfo[index] = !sectionExpandedInfo[index]
self.tableView.reloadSections(NSIndexSet(index: index) as IndexSet, with: .automatic)
}
}
}
插入或删除部分:
func controller(controller: NSFetchedResultsController<NSFetchRequestResult>, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
switch type {
case .insert:
self.sectionExpandedInfo.insert(true, at: sectionIndex)
self.tableView.insertSections(NSIndexSet(index: sectionIndex) as IndexSet, with: .fade)
case .delete:
self.sectionExpandedInfo.remove(at: sectionIndex)
self.tableView.deleteSections(NSIndexSet(index: sectionIndex) as IndexSet, with: .fade)
default:
return
}
}
再次向pbasdf致敬
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.