iOS 8:从 NSFetchedResultsController 的委托中捕获异常,无效更新:第 0 节中的行数无效

Posted

技术标签:

【中文标题】iOS 8:从 NSFetchedResultsController 的委托中捕获异常,无效更新:第 0 节中的行数无效【英文标题】:iOS 8: An exception was caught from the delegate of NSFetchedResultsController, Invalid update: invalid number of rows in section 0 【发布时间】:2016-02-18 09:45:55 【问题描述】:

来自我的NSFetchedResultsControllerDelegate 的完整日志,适用于 ios 8:

---开始--- --------我 --------我 --------我 ---完成--- 2016-02-18 10:42:22.433 POSowner[9784:66814] *** 断言失败 -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-3347.44.2/UITableView.m:1623 2016-02-18 10:42:22.440 POSowner[9784:66814] CoreData:错误:严重的应用程序错误。在调用 -controllerDidChangeContent: 期间,从 NSFetchedResultsController 的委托中捕获了一个异常。无效更新:第 0 节中的行数无效。更新后现有节中包含的行数 (1) 必须等于更新前该节中包含的行数 (1),加上或减去数字从该部分插入或删除的行数(1 插入,0 删除)加上或减去移入或移出该部分的行数(0 移入,0 移出)。使用 userInfo (null) ---开始--- --------D --------D --------D ---完成---

对于 iOS 9:

---开始--- --------D --------D --------D --------我 --------我 --------我 ---完成---

这是我的NSFetchedResultsControllerDelegate

//MARK: - NSFetchedResultsControllerDelegate

func controllerWillChangeContent(controller: NSFetchedResultsController) 
    print("---STARTED---")
    tableView.beginUpdates()


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

    let indexSet = NSIndexSet(index: sectionIndex)

    switch type 
    case .Insert:
        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:
        print("--------I")
        if let newIndexPath = newIndexPath 
            tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Fade)
        
    case .Delete:
        print("--------D")
        if let indexPath = indexPath 
            tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
        
    case .Update:
        print("--------U")
        if let indexPath = indexPath, let cell = tableView.cellForRowAtIndexPath(indexPath) as? PBOTableViewCell 
            updateCell(cell, indexPath: indexPath)
        
    case .Move:
        print("--------M")
        if let indexPath = indexPath 
            if let newIndexPath = newIndexPath 
                tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
                tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Fade)
            
        
    


func controllerDidChangeContent(controller: NSFetchedResultsController) 
    print("---FINISHED---")
    tableView.endUpdates()

UITableViewDataSourceDelegate:

override func numberOfSectionsInTableView(tableView: UITableView) -> Int 

    var numberOfSections = 0

    if let sections = fetchedResultsController?.sections 
        numberOfSections = sections.count
    

    return numberOfSections


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

    let workday = workDayObjectForSection(section)
    return workday.worktimes.count


private func workDayObjectForSection(section: Int) -> PBOUserWorkDay 

    let sections: NSArray? = fetchedResultsController.sections!
    let sectionInfo = sections?.objectAtIndex(section) as? NSFetchedResultsSectionInfo
    let workdays = sectionInfo?.objects as! [PBOUserWorkDay]

    return workdays[0]

在 iOS 8 上发生。有任何解决方法吗? 完全相同的操作在 iOS 9 上就像一个魅力。而且每次它都不适用于 iOS 8。

【问题讨论】:

您确定您正在编辑的项目数量正确吗?我多次遇到同样的问题,这是我插入新数据时的逻辑错误 @bobby,我更新了问题。如果项目数不正确,则在 iOS 9 上将无法运行。如果您需要,我可以添加更多代码... 所以你是说在iOS9上使用相同的数据(完全相同的数据)你不会崩溃,对吧? 我假设您正在使用 Core Data,并且 iOS9 的 Core Data 具有诸如 unicity 之类的新功能。所以它可能在 iOS 9 上工作,因为 FatchController 检测到你只是在编辑一个条目,而 iOS 8 失败因为它认为你正在添加一个新条目,但你没有 是的,数据一模一样,在ios 9上没有崩溃。经过艰苦的测试。当然,我使用核心数据。你可能是对的......任何想法如何解决这个问题?我可以试试…… 【参考方案1】:

它看起来像一个错误,我过去遇到过。请尝试下面的代码,也许它会有所帮助。

- (void)controller:(NSFetchedResultsController *)controller
   didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath
     forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath


    switch (type) 

        case NSFetchedResultsChangeDelete: 
            // your code
         break;

        case NSFetchedResultsChangeInsert: 
            // your code
         break;

        case NSFetchedResultsChangeUpdate: 
            // your code
         break;

        case NSFetchedResultsChangeMove: 
            // BUG: Move is called where Update is expected
            if ([indexPath compare:newIndexPath] == NSOrderedSame) 
                // object is not moved, so perfrom the same logic as for NSFetchedResultsChangeUpdate

                // your code
            
            else 
                // object is moved, actually

                // your code
            
         break;

        default:
            break;
    

我不记得在哪里找到了正确方向的解决方案/想法。

【讨论】:

以上是关于iOS 8:从 NSFetchedResultsController 的委托中捕获异常,无效更新:第 0 节中的行数无效的主要内容,如果未能解决你的问题,请参考以下文章

NSLayoutConstraint layout Margin 从 iOS 7 到 iOS 8 的变化

如何从应用程序 iOS 8 启用/禁用推送通知

iOS 8 照片框架:从 PHAsset 获取文件名

BLE 在将数据从 iOS 7.1 发送到 iOS 8 时花费了太多时间

如何从 Today Extensions(iOS 8) 访问核心数据详细信息?

iOS 8 从 PHAsset 快速加载图像