NSFetchedResultsController 在向第二部分插入行时在第一部分返回错误的行数

Posted

技术标签:

【中文标题】NSFetchedResultsController 在向第二部分插入行时在第一部分返回错误的行数【英文标题】:NSFetchedResultsController returns wrong number rows in first section while inserting rows to second section 【发布时间】:2016-08-30 09:03:38 【问题描述】:

这是我的NSFetchedResultsControllerDelegate,上面有一些指纹:

//MARK: - NSFetchedResultsControllerDelegate

func controllerWillChangeContent(controller: NSFetchedResultsController) 
    tableView.beginUpdates()


func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) 

    let indexSet = NSIndexSet(index: sectionIndex)

    switch type 
    case .Insert:

        print("SECTION INSERT --->>> \(sectionIndex)")
        tableView.insertSections(indexSet, withRowAnimation: .Fade)

    case .Delete:

        tableView.deleteSections(indexSet, withRowAnimation: .Fade)

    case .Update:

        fallthrough

    case .Move:

        tableView.reloadSections(indexSet, withRowAnimation: .Fade)
    


func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) 

    switch type 
    case .Insert:

        if let newIndexPath = newIndexPath 

            print("ROW INSERT --->>> \(newIndexPath)")
            tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Fade)
        

    case .Delete:

        if let indexPath = indexPath 
            tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
        

    case .Update:

        if let indexPath = indexPath 
            tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
        

    case .Move:

        if let indexPath = indexPath, let newIndexPath = newIndexPath 

            tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
            tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Fade)
        
    

    print("First sumOfRows --->>> \(fetchedResultsController.fetchedObjects?.count)")

    var sumOfRows = 0
    for section in fetchedResultsController.sections! 

       sumOfRows += section.objects!.count
    

    print("Second sumOfRows--->>> \(sumOfRows)")


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


//MARK: - UITableViewDataSource

func numberOfSectionsInTableView(tableView: UITableView) -> Int 
    return fetchedResultsController?.sections?.count ?? 0


func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 

    print("Section --->>> \(section)")
    print("Number of rows in section --->>> \(fetchedResultsController.sections![section].objects!.count)")
    return fetchedResultsController.sections![section].objects!.count

BEFORE插入我只有一个部分,那里只有一行。

当我插入新行时,控制台上的输出如下:

SECTION INSERT --->>> 1
ROW INSERT --->>> <NSIndexPath: 0xc000000000000116> length = 2, path = 1 - 0
First sumOfRows --->>> Optional(2)
Second sumOfRows--->>> 3
Section --->>> 0
Number of rows in section --->>> 2
Section --->>> 1
Number of rows in section --->>> 1

我得到的错误:

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

为什么 NSFetchedResultsController 在节中返回错误的行数?

【问题讨论】:

没错,同样的问题;(一些FRC的错误或代码中的错误逻辑? 该错误与您在未正确开始或完成表视图更新的情况下插入和删除数据行有关 - 您的数据集与您的视图不匹配。我建议您尝试在每个函数中包含对 beginUpdatesendUpdates 的调用,而不是跨函数拆分。 (您不知道 swift 在这些 FRC 委托方法之间做了什么,这可能会扰乱您更新视图的尝试。) @andrewbuilder 没有理由更改 FRC 的委托方法(尤其是 begin/endUpdates)。它们由 Xcode 在 Core Data 模板中隐式创建,如果开发人员遵守管理数据源的规则,它们可以完美地工作。 @vadian 那么你为什么不把它写成你对 OP 的回答而不是给我发消息呢?我经常将代码添加到我的 FRC 委托方法中,以非常精细地管理应用程序视图行为,并且我假设 OP 也有类似的需求。也许不是这样? @andrewbuilder 在每个函数中调用beginUpdates() 到底是什么意思? 【参考方案1】:

您的numberOfRowsInSection 方法只需使用numberOfObjects 而不是objects!.count

请看this的回答。

【讨论】:

以上是关于NSFetchedResultsController 在向第二部分插入行时在第一部分返回错误的行数的主要内容,如果未能解决你的问题,请参考以下文章

在 Core Data 应用程序中调用 performFetch 后,是不是需要手动更新表视图?