NSFetchedResultsController 中的排序部分

Sort Sections in NSFetchedResultsController

我正在使用 NSFetchedResultsController 来管理我的 tableView,问题是当添加另一个部分时,NSFetchedResultsController 自动将它放在索引 0 处,这导致我的应用程序出现几个问题。下面是我如何设置我的 NSFetchedResultsController,我正在获取类型 CDSet,并且每个部分的类型都是 exercise

两者的关系如下 CDSet <<---> Exercise

如何按 exercise.exerciseIndex 对部分进行排序?

let fetchRequest:NSFetchRequest<CDSet> = CDSet.fetchRequest()
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "set_index", ascending: true)]
fetchRequest.predicate = NSPredicate(format: "exercise.workout == %@", currentWorkout)

fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: DataController.shared.context, sectionNameKeyPath: "exercise.exerciseIndex", cacheName: nil)


fetchedResultsController.delegate = self

do {
    try fetchedResultsController.performFetch()
} catch {
    
}

更新: 我已将 sortDescriptor 更新为以下内容:

fetchRequest.sortDescriptors = [NSSortDescriptor(key: "exercise.exerciseIndex", ascending: true), NSSortDescriptor(key: "set_index", ascending: true)]

但我现在在尝试添加第二部分时遇到此错误:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of sections. The number of sections contained in the table view after the update (2) must be equal to the number of sections contained in the table view before the update (1), plus or minus the number of sections inserted or deleted (2 inserted, 0 deleted).'

不确定为什么它在我只指定 1 时尝试插入 2

这是我的 NSFetchedResultsController 委托方法:

func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
        tableView.beginUpdates()
    }
    
    func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
        tableView.endUpdates()
    }
    
    
    func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
        
        let indexPath = IndexPath(row: 0, section: sectionIndex)
        let indexSet = IndexSet(indexPath)
        tableView.insertSections(indexSet, with: .fade)
    }
    
    func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
        
        
        switch type {
        case .insert:
            tableView.insertRows(at: [newIndexPath!], with: .fade)
        case .delete:
            tableView.deleteRows(at: [newIndexPath!], with: .fade)
        default:
            break
        }
    }

您必须指定两个排序描述符。

  • 第一个对sections进行排序,必须等同于section key path
  • 第二个对部分中的项目进行排序。

编辑:

controller(_:didChange: atSectionIndex:for:)的通常实现是

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
      switch type {
          case .insert: self.tableView.insertSections(IndexSet(integer: sectionIndex), with: .fade)
          case .delete: self.tableView.deleteSections(IndexSet(integer: sectionIndex), with: .fade)
          default: return
      }
  }