I have a UITableView backed by an NSFetchedResultsController.
The table view presents chat conversations.
I have a few chat conversations type (NSNumber), the table view separated for sections depending on your chat conversation type, So, if you have a 3 conversations type you have 3 sections in your table view.
The chat conversations sorted by date (each conversation contains last message dade).
The problem is when the user update the chat conversation type, the app crash with the following error:
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]'
I Initializes the NSFetchedResultsController with the following code:
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
}()
My NSFetchedResultsController delegate code:
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()
}
}
All the core data model update with the same NSManagedObjectContext.
I'm using with https://github.com/jessesquires/JSQCoreDataKit wrapper
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)")
}
}
}
Any advice?
Thanks
The NSFetchedResultsControllerDelegate
methods are called inside an NSManagedObjectContextObjectsDidChangeNotification
handler. You should put breakpoints in your method implementations for these in order to find the offending code. Chances are good it has to do with manipulating your table view and numberOfSectionsInTableView:
or tableView:numberOfRowsInSection:
not returning an appropriate value (so breakpoints in these methods may be useful as well).