使用NSFetchedResultsController更新节

时间:2016-09-18 22:35:08

标签: ios swift core-data nsfetchedresultscontroller

我有一个名为ToDoItem的实体。其中有三个属性:

@NSManaged var toDoString: String?
@NSManaged var creationDate: NSDate?
@NSManaged var isComplete: NSNumber?

我正在尝试创建NSFetchedResultsController,根据isComplete变量显示两个部分。我能成功地做到这一点:

lazy var fetchedResultsController: NSFetchedResultsController = {

    let questionAnswerFetchRequest = NSFetchRequest(entityName: "ToDoItem")

    let questionAnswerFetchSortDescriptor = NSSortDescriptor(key: "creationDate", ascending: false)
    questionAnswerFetchRequest.sortDescriptors = [questionAnswerFetchSortDescriptor]

    let frc = NSFetchedResultsController(
        fetchRequest: questionAnswerFetchRequest,
        managedObjectContext: (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext,
        sectionNameKeyPath:"isComplete",
        cacheName: nil)

    frc.delegate = self
    return frc
}()

我也实现了这样的删除方法:

//
// MARK: Fetched Results Controller Delegate Methods
//
func controllerWillChangeContent(controller: NSFetchedResultsController) {
    tableView.beginUpdates()
}

func controllerDidChangeContent(controller: NSFetchedResultsController) {
    tableView.endUpdates()
}

func controller(controller: NSFetchedResultsController,
                didChange sectionInfo: NSFetchedResultsSectionInfo,
                          atSectionIndex sectionIndex: Int,
                                         for type: NSFetchedResultsChangeType) {

    switch (type) {
    case .Insert:
        self.tableView.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade)
        break
    case .Delete:
        self.tableView.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade)
        break
    default:
        break
    }

}

func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
    switch (type) {
    case .Insert:
        if let indexPath = newIndexPath {
            tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
        }
        break;
    case .Delete:
        if let indexPath = indexPath {
            tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
        }
        break;
    case .Update:
        if let indexPath = indexPath {
            tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
        }
        break;
    case .Move:
        if let indexPath = indexPath {
            tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
        }

        if let newIndexPath = newIndexPath {
            tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Fade)
        }
        break;
    }
}

问题是,当我更新isComplete属性时,我收到此错误:

  

CoreData:错误:严重的应用程序错误。抓住了一个例外   在调用期间来自NSFetchedResultsController的委托   -controllerDidChangeContent :.无效更新:无效的节数。表视图中包含的节数   更新(1)必须等于包含的部分数   更新前的表视图(0),加号或减号   插入或删除的部分(插入0,删除0)。用户信息   (空)

我理解这是什么,我只是不明白为什么它导致了这个错误。我根据文档实现了委托方法.....

我更新了我的NSFetchedResultsController创建,为@ wain的答案添加了另一个sortDescriptor,如下所示:

lazy var fetchedResultsController: NSFetchedResultsController = {

        let questionAnswerFetchRequest = NSFetchRequest(entityName: "ToDoItem")

        let isCompleteSortDescriptor   = NSSortDescriptor(key: "isComplete", ascending: false)
        let creationDateSortDescriptor = NSSortDescriptor(key: "creationDate", ascending: false)

        questionAnswerFetchRequest.sortDescriptors = [isCompleteSortDescriptor, creationDateSortDescriptor]

        let frc = NSFetchedResultsController(
            fetchRequest: questionAnswerFetchRequest,
            managedObjectContext: (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext,
            sectionNameKeyPath:"isComplete",
            cacheName: nil)

        frc.delegate = self
        return frc
    }()

我添加了一些断点,事实证明这个委托方法永远不会被调用:

func controller(controller: NSFetchedResultsController,
                didChange sectionInfo: NSFetchedResultsSectionInfo,
                          atSectionIndex sectionIndex: Int,
                                         for type: NSFetchedResultsChangeType) {

    switch (type) {
    case .Insert:
        self.tableView.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade)
        break
    case .Delete:
        self.tableView.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade)
        break
    default:
        break
    }
}

导致与上面发布的错误相同的错误。关于为什么永远不会被召唤的任何想法?

1 个答案:

答案 0 :(得分:3)

您需要为isComplete添加排序描述符。它应该是第一个排序描述符,然后是你的日期。

基本上,排序和部分需要兼容,而你的目前不是。