【问题标题】:CoreData serious error when using 2 NSFetchedResultsController on the same table在同一张表上使用 2 个 NSFetchedResultsController 时 CoreData 出现严重错误
【发布时间】:2016-06-28 09:41:24
【问题描述】:

我的问题是我收到 CoreData 严重错误,但我不知道为什么。错误类似于:

Core Data Serious Application Error at controllerDidChangeContent

我有一个控制器显示用户列表(存储在 CoreData 的用户表中)。非常直接。

在第二个视图控制器中,我从服务器检索用户列表,并检索存储在 CoreData 中的用户,以查看本地是否已经有相同的用户(在这种情况下,我更改单元格的颜色背景)我还在第一部分的第一个单元格中添加了一个带有标题的标题。

这是我在第一个 viewController init 构造函数中初始化 fetchController 的方式:

let modelMethodNameForSection = "firstCharOfFirstname"
let requestHelper = NSFetchRequest(entityName: modelEntityClass)
requestHelper.predicate = NSPredicate(format: "friend.groupA == YES")
requestHelper.sortDescriptors = [sortDescriptor]

let managedObjectCtx = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext

fetchedResultsController = NSFetchedResultsController(fetchRequest: requestHelper, managedObjectContext: managedObjectCtx, sectionNameKeyPath: modelMethodNameForSection, cacheName: nil)

以下是代表:

  //MARK: - NSFetchedResultsControllerDelegate
  func controllerWillChangeContent(controller: NSFetchedResultsController)
  {
    tableView!.beginUpdates()
  }

  func controllerDidChangeContent(controller: NSFetchedResultsController)
  {
    tableView!.endUpdates()
    if let fetchedObjects = controller.fetchedObjects {
      segmentedControlDelegate?.updateSegment(fetchedObjects.count, listType: ProfilePeopleListType.Friends) //listType doesn t matter here
    }
  }

  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 {
        if let cell = tableView!.cellForRowAtIndexPath(indexPath) as? UserViewCell { //We need to check that it's a UserViewCell, because it can be another class
          configureCell(cell, atIndexPath: indexPath)
        }
      } 
      break
    case .Move:
      if let indexPath = indexPath {
        tableView!.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
      }

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

  func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType)
  {
    switch type {
    case .Insert:
      tableView!.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade)
    case .Delete:
      tableView!.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade)
    default:
      return
    }
  }

这是第二个 viewController 显示与服务器合并的结果的代码:

let modelMethodNameForSection = "firstCharOfFirstname"
let requestHelper = NSFetchRequest(entityName: modelEntityClass)
requestHelper.predicate = NSPredicate(format: "friend.groupA == YES")
requestHelper.sortDescriptors = [sortDescriptor]

let managedObjectCtx = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext

fetchedResultsController = NSFetchedResultsController(fetchRequest: requestHelper, managedObjectContext: managedObjectCtx, sectionNameKeyPath: modelMethodNameForSection, cacheName: nil)

我的表格视图在section[0]的行[0](表格顶部)中显示包含标题的标题

  //MARK: - NSFetchedResultsControllerDelegate
  //When the local database Friends table changes we are notified
  func controllerWillChangeContent(controller: NSFetchedResultsController)
  {

  }

  func controllerDidChangeContent(controller: NSFetchedResultsController)
  {

  }

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

    //We refresh the lists with new data from local Database
    let listFriendsFilterBlock = peopleListWithOwnerFriendsFilter()
    tableView?.reloadData()
  }

  func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType)
  {
    //We don't have any sections in the users list merged with server data

  }

编辑 崩溃日志:

[;2016-03-16 18:51:10.511 *** -[UITableView 中的断言失败 _endCellAnimationsWithContext:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3512.29.5/UITableView.m:1720 2016-03-16 18:51:10.511 CoreData:错误:严重的应用程序错误。 从 的代表处捕获了一个异常 NSFetchedResultsController 在调用期间 -controllerDidChangeContent:。无效更新:第 0 节中的行数无效。现有节中包含的行数 更新后(2)必须等于包含的行数 更新前的那个部分(1),加上或减去行数 从该部分插入或删除(0 插入,0 删除)和加上 或减去移入或移出该部分的行数(0 移动 入,0 移出)。与 userInfo (null)

【问题讨论】:

  • 告诉我们您收到的严重错误消息
  • 在这里,行数有问题。
  • 知道 NSFetchedResultsController 甚至不知道 tableView (我们甚至没有在代码中给出指向它的指针),我真的不明白异常是如何发生的

标签: ios swift uitableview core-data nsfetchedresultscontroller


【解决方案1】:

从错误消息中,您的 FRC 告诉您(委托人)某些事情发生了变化,因此您正在更新您的数据源数据,但您没有正确地告诉表视图有关插入/删除的信息.

在这种特定情况下,已插入 1 个项目,并且尚未告知表格视图有任何插入。

这可能(虽然很难说)与:

//We refresh the lists with new data from local Database
let listFriendsFilterBlock = peopleListWithOwnerFriendsFilter()
tableView?.reloadData()

因为这种刷新表的方法应该在controllerDidChangeContent 而不是didChangeObject 中实现。在重新加载之前,您应该知道更改已完成。

【讨论】:

  • 我将代码移到了 controllerDidChangeContent 中,但问题仍然存在。一个问题是我真的没有办法知道哪个 tableview 触发了这个问题。我所知道的是,当错误发生时,带有 switch-case 的 tableView 布局会被破坏。就像 tableview 顶部的内容 inset 变成了一个非常巨大的空白。第二个问题是我不想告诉第二个视图控制器上的插入/删除,因为我显示服务器和客户端之间混合的数据......我现在更喜欢简单地刷新整个列表。为什么 coredata 和 tableview 之间存在链接
  • 那么第二个表更新真的是由 FRC 驱动的吗?我不确定为什么您不知道要更新哪个,因为它们位于不同的控制器中。
  • 第二个 tableView 只是使用一个数据源,它是 FRC fetchedObjects 和服务器数据之间的合并。当 coredata 发生变化时,我请求服务器并完全重新加载表。也许我也必须先清空它?
猜你喜欢
  • 2014-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-05
  • 1970-01-01
相关资源
最近更新 更多