带有 NSFetchResultController 的 CoreData:在 fetchObjects 中使用 属性 进行无效更新

CoreData with NSFetchResultController :Invalid update with with a property in fetchObjects

Xcode 报告了一个严重的问题:

1.我有一个 NSFetchResultsController

var fetchedResultsController: NSFetchedResultsController {
    if _fetchedResultsController != nil {
        return _fetchedResultsController!
    }

    let fetchRequest = NSFetchRequest()
    // Edit the entity name as appropriate.
    let entity = NSEntityDescription.entityForName("Choice", inManagedObjectContext: NSManagedObjectContext.MR_defaultContext())
    fetchRequest.entity = entity

    // Set the batch size to a suitable number.
    fetchRequest.fetchBatchSize = 10

    // Edit the sort key as appropriate.
    let sortDescriptor = NSSortDescriptor(key: "id", ascending: false)
    let sortDescriptors = [sortDescriptor]

    fetchRequest.sortDescriptors = sortDescriptors

    //NSPredicate
    let predicate = NSPredicate(format: "decision.id = %@", decision.id!)
    fetchRequest.predicate = predicate

    // Edit the section name key path and cache name if appropriate.
    // nil for section name key path means "no sections".
    let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: NSManagedObjectContext.MR_defaultContext(), sectionNameKeyPath: nil, cacheName: nil)
    aFetchedResultsController.delegate = self
    _fetchedResultsController = aFetchedResultsController

    do{
        try _fetchedResultsController?.performFetch()
    }catch let error as NSError {
        print(error)
    }

    return _fetchedResultsController!
}

2。我有一个按钮可以添加操作:

@IBAction func didTouchAddChoiceButton(sender: UIButton) {
    let choice = Choice.MR_createEntity() as! Choice
    choice.id = GDUtils.CMUUID()
    choice.decision = decision
    NSManagedObjectContext.MR_defaultContext().MR_saveToPersistentStoreAndWait()
}

3。添加此实体后。我有一个控制器来处理像这样更新 tableView

func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
    switch(type){
    case .Insert:
        tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Top)

    case .Delete:
        tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)

    case .Update:
        tableView.cellForRowAtIndexPath(indexPath!)

    case .Move:
        tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Left)
        tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade)
    }
}

4.But 问题发生了:每次我尝试从 fetchedObjects 更改实体的 属性 时:

let chosenChoice = fetchedResultsController.objectAtIndexPath(currentIndextPath!) as! Choice
    chosenChoice.name = tableCell.choiceName.text

我收到这条消息:

CoreData: error: Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (1) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out). with userInfo (null)

谁能帮我弄清楚发生了什么事?

确保您分配给 NSFetchResultsController 的 managedOjectContext 与您创建新 Choice NSManagedObject 的位置相同。

已添加

in "case .Update" 代码为您提供了表格视图的单元格。并且您需要更新 tableView 单元格数据才能避免出现该错误。至少在单元格中更改/(假装更改)某事。

cell = tableView.cellForRowAtIndexPath(indexPath!)
cell.choiceName.text = "empty"

iOS8 上的 NSFetchedResultsController 中存在错误,其中 FRC 调用 .Insert 而不是 .Update。我解决了这个问题,当在 iOS8.

上调用 .Insert 时,我正在完全重新加载 table
case .Insert:
    guard let newIndexPath = newIndexPath else { return }

    // iOS8 bug when FRC calls insert instead of Update
    if #available(iOS 9, *) {
        // insert item normally
    } else {
        // reload everything
    }