更改 sectionNameKeyPath 属性项属性时 NSFetchedResultsController 崩溃

Posted

技术标签:

【中文标题】更改 sectionNameKeyPath 属性项属性时 NSFetchedResultsController 崩溃【英文标题】:NSFetchedResultsController crash when changing sectionNameKeyPath attribute item property 【发布时间】:2015-12-14 16:28:27 【问题描述】:

我有一个由 NSFetchedResultsController 支持的 UITableView。

表格视图呈现聊天对话。

我有几个聊天对话类型(NSNumber),表格视图根据您的聊天对话类型分隔为部分,因此,如果您有 3 个对话类型,那么您的表格视图中有 3 个部分。

按日期排序的聊天对话(每个对话都包含最后一条消息)。

问题是当用户更新聊天对话类型时,应用程序崩溃并出现以下错误:

CoreData: error: Serious application error.  Exception was caught during Core Data change processing.  This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification.  *** -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0] with userInfo (null)
2015-12-14 18:18:24.831 Reporty[1328:108995] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]'

我使用以下代码初始化 NSFetchedResultsController:

  lazy var fetchedResultsController: NSFetchedResultsController = 

    let fetchRequest = NSFetchRequest(entityName: "ChatConversation")
    fetchRequest.sortDescriptors = [
      NSSortDescriptor(key: "conversationType", ascending: false),
      NSSortDescriptor(key: "lastMessageDate", ascending: false)
    ]

    let frc = NSFetchedResultsController(
      fetchRequest: fetchRequest,
      managedObjectContext: self.chatManager.getChatMainContext(),
      sectionNameKeyPath: "conversationType",
      cacheName: nil)

    frc.delegate = self

    return frc
  ()

我的 NSFetchedResultsController 委托代码:

extension ChatConversationsViewController: NSFetchedResultsControllerDelegate 

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

  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:
        break
      
  

  func controller(
    controller: NSFetchedResultsController,
    didChangeObject anObject: AnyObject,
    atIndexPath indexPath: NSIndexPath?,
    forChangeType type: NSFetchedResultsChangeType,
    newIndexPath: NSIndexPath?) 
      switch type 
      case .Insert:
        tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade)
      case .Delete:
        tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
      case .Update:
        configureCell(tableView.cellForRowAtIndexPath(indexPath!) as! ChatConversationTableViewCell, atIndexPath: indexPath!)
      case .Move:
        tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
        tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade)
      
  

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

使用相同的 NSManagedObjectContext 更新所有核心数据模型。

我正在使用 https://github.com/jessesquires/JSQCoreDataKit 包装器

self.stack!.mainContext.performBlockAndWait 

//update the model
saveContext(self.stack!.mainContext)  (result: CoreDataSaveResult) in
              switch result 
              case .Success():
                print("Success")
              case .Failure(let error):
                print("Error: \(error)")
              
            

有什么建议吗?

谢谢

【问题讨论】:

删除 github.com/jessesquires/JSQCoreDataKit 并直接使用 CoreData,看起来它或您的应用正在侦听 NSManagedObjectContextObjectsDidChangeNotification 通知并出现问题 是的,很难基于某些第三方框架进行调试。默默无闻比方便更重要。 【参考方案1】:

NSFetchedResultsControllerDelegate 方法在 NSManagedObjectContextObjectsDidChangeNotification 处理程序中调用。你应该在你的方法实现中为这些设置断点,以便找到有问题的代码。很有可能它与操纵您的表格视图和 numberOfSectionsInTableView:tableView:numberOfRowsInSection: 没有返回适当的值有关(因此这些方法中的断点也可能很有用)。

【讨论】:

以上是关于更改 sectionNameKeyPath 属性项属性时 NSFetchedResultsController 崩溃的主要内容,如果未能解决你的问题,请参考以下文章

从关系中观察到 sectionNameKeyPath 的变化

自定义核心数据 SectionNameKeyPath

NSFetchedResultsController、sectionNameKeyPath 和无数据日期的部分

更新现有 NSFetchedResultsController 中的 sectionNameKeyPath

Swift:使用 sectionNameKeyPath 的单元格的 indexPath

带有 sectionNameKeyPath 的 NSFetchedResultsController