首页 > 解决方案 > 在 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
        }
    }

标签: iosswiftcore-datansfetchedresultscontroller

解决方案


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

  • 第一个对section进行排序,它必须等同于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
      }
  }

推荐阅读