[英]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.