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

时间:2016-01-26 08:16:00

标签: ios swift uitableview core-data nsfetchedresultscontroller

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.但是问题发生了:每次我尝试从fetchedObjects更改实体的属性时:

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

我收到了这条消息:

  

CoreData:错误:严重的应用程序错误。在调用-controllerDidChangeContent:期间,从NSFetchedResultsController的委托中捕获到异常。无效更新:第0节中的行数无效。更新(1)后现有部分中包含的行数必须等于更新前的该部分中包含的行数(1),加上或减去数字从该部分插入或删除的行(插入1个,删除0个)并加上或减去移入或移出该部分的行数(0移入,0移出)。 with userInfo(null)

任何人都可以帮我弄清楚发生了什么吗?

2 个答案:

答案 0 :(得分:2)

iOS8上的NSFetchedResultsController存在一个错误,其中FRC调用.Insert而不是.Update。我解决了它的方式,当我在iOS8上调用.Insert时,我正在重新加载表。

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
    }

答案 1 :(得分:1)

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

ADDED

“case .Update”代码中的

为您提供tableview的单元格。并且您需要更新tableView单元格数据以获取该错误。至少改变/(假装改变)在单元格中。

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