Tengo un controlador estándar de vista dividida, con una vista detallada y una vista de tabla. Presionar un botón en la vista de detalle puede hacer que un objeto cambie su ubicación en el orden de la vista de tabla. Esto funciona bien, siempre que el cambio de pedido resultante no dé como resultado que se agregue o elimine una sección. Es decir. un objeto puede cambiar su orden en una sección o cambiar de una sección a otra. Esos cambios de pedido funcionan correctamente sin problemas. Pero, si el objeto intenta moverse a una sección que aún no existe, o es el último objeto que deja una sección (por lo tanto, requiere que la sección se vaya a eliminar), entonces la aplicación falla."didChangeSection:" Método delegado NSfetchedResultsController que no se llama
NSFetchedResultsControllerDelegate tiene métodos para manejar las secciones que se agregan y eliminan que se deben llamar en esos casos. Pero esos métodos de delegado no se llaman por algún motivo.
El código en cuestión, es repetitivo:
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
NSLog(@"willChangeContent");
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
NSLog(@"didChangeSection");
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath {
NSLog(@"didChangeObject");
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
NSLog(@"didChangeContent");
[self.tableView endUpdates];
[detailViewController.reminderView update];
}
Inicio de la aplicación y, a continuación, haciendo que el último objeto de dejar una sección de resultados en la siguiente salida:
2011-01-08 23:40:18.910 Reminders[54647:207] willChangeContent
2011-01-08 23:40:18.912 Reminders[54647:207] didChangeObject
2011-01-08 23:40:18.914 Reminders[54647:207] didChangeContent
2011-01-08 23:40:18.915 Reminders[54647:207] *** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-1145.66/UITableView.m:825
2011-01-08 23:40:18.917 Reminders[54647:207] Serious application error. Exception was caught during Core Data change processing: Invalid update: invalid number of sections. The number of sections contained in the table view after the update (5) must be equal to the number of sections contained in the table view before the update (6), plus or minus the number of sections inserted or deleted (0 inserted, 0 deleted). with userInfo (null)
Como se puede ver , "willChangeContent", "didChangeObject" (moviendo el objeto en cuestión), y "didChangeContent" se llamaron todos correctamente. Basado en la documentación NSFetchedResultsControllerDelegate de Apple, "didChangeSection" debería haberse llamado antes de "didChangeObject", lo que habría evitado que la excepción causara el bloqueo.
Así que supongo que la pregunta es ¿cómo puedo asegurar que se llame a didChangeSection?
¡Gracias de antemano por cualquier ayuda!
Tengo un problema muy similar en mi proyecto. El didChangeSection no parece ser llamado cuando se supone que debe hacerlo. Estoy usando "objectID.URIRepresentation" para la secciónNameKeyPath porque quiero que cada objeto esté en su propia sección. Estoy probando en el simulador de iPhone 5.1. Mi FRC clasifica en función del valor (aumentando a disminuir), por lo que si el valor de un objeto cambia, el orden de mis secciones también debería cambiar, pero nunca se llama a la función didChangeSection. ¿Tienes alguna intuición de por qué esto puede estar pasando? Gracias. – klyngbaek
Luché también con esto, especificando nil para la secciónNameKeyPath al principio. Cuando se eliminaron todos los objetos, devolví 0 para el número de secciones en el método de origen de datos de tableView (fetchedObjects == 0), que rompió el tableView. Debería especificar algún tipo de sectionNameKeyPath si necesita que se dispare este método delegado. Esto ahora parece bastante claro, solo pensé que lo compartiría con aquellos con la cabeza de madera como yo. – Schoob
Tuve un problema muy similar, nuestra diferencia era que estaba usando un atributo transitorio, mientras que yo no estaba usando ningún atributo en el modelo * de datos * en absoluto * - Tenía una propiedad solo en la categoría, con getter y setter personalizados para todas las cosas de 'willAccess' ...' didChange'. Todo parecía perfecto, pero 'didChangeSection 'nunca se llamaría. Lo que resolví para mí fue finalmente crear un atributo transitorio para representarlo. Entonces podría eliminar mi setter personalizado y adaptar ligeramente mi getter personalizado para usar -primitiveValueForKey :. – Gobe