2011-01-09 11 views
5

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!

Respuesta

1

Este problema fue causado por el uso de un atributo transitorio como sectionNameKeyPath. Cuando, en su lugar, almacené el atributo utilizado para la sección Nombre clave clave en la base de datos, el problema desapareció. No sé si hay una forma de actualizar las secciones en función de los cambios en el contenido de NSFetchedResultsController cuando se utiliza un atributo transitorio como sectionNameKeyPath. Por ahora estoy considerando esto una limitación de atributos transitorios.

+0

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

+0

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

+0

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

1

Estoy haciendo lo mismo en mi aplicación (propiedad transitoria en la secciónNameKeyPath) y no veo el problema que está experimentando. Estoy probando esto en iOS 4.2.1 ... Hay un error conocido en el que no puedes confiar en ninguna de las devoluciones de llamadas de delegados de FRC en iOS 3.X, tienes que hacer un completo [tableView reloadData] en el controladorDidChangeContent: message. see the FRC documentation

He probado pasar de una sección existente con otra entrada a una sección inexistente, así como de una sección con una sola fila a otra sección inexistente.

+0

Gracias por señalar esto Brent. Estoy en iOS 4.1, así que es muy posible que haya encontrado un error que desde entonces se solucionó. – robenk

+0

¿obtienes este mismo comportamiento en el simulador? ¿Has probado versiones posteriores? (Tengo un interés egoísta porque dependo de esta característica y no quiero que los clientes me informen errores;) Lamentablemente, he actualizado todos mis iDevices a la última versión posible. –

+0

Hola Brent, el problema original fue descubierto y probado _only_ en el simulador. es decir, nunca probé la aplicación en un dispositivo real mientras experimentaba este problema. FYI, ahora actualicé el SDK a 4.2 y terminé por recuperar las propiedades transitorias, y ya no tengo ningún problema. Eso es una prueba más de que esto era un problema de SDK en 4.1 – robenk

Cuestiones relacionadas