Pensé que got it. Pero un nuevo bloqueo que encontré en mi aplicación dice lo contrario. Entonces, cualquiera sabe el código realmente correcto para NSFetchedResultsChangeUpdate
cuando newIndexPath no es nada y no es lo mismo que indexPath en -controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:
?Cómo usar newIndexPath para NSFetchedResultsChangeUpdate?
Respuesta
Me encontré con un bloqueo en la actualización, y parece que newIndexPath
se proporciona como una ruta de índice en los objetos del controlador de resultados obtenidos cuando esa ruta de índice no coincide con la ruta de índice necesaria para recuperar la celda de la tabla. Considere lo siguiente:
- Una vista de tabla tiene una sección en el índice 0 con 15 elementos.
- El elemento en el índice 13 (la segunda a la última opción) se suprime
- El elemento en el índice 14 (el último elemento) se actualiza
En el caso anterior, en el supuesto de que está utilizando [tableView beginUpdates]
y [tableView endUpdates]
en los métodos apropiados controllerWill/DidChangeContent:
, necesitará usar el parámetro indexPath
para recuperar la celda de la tabla para actualizar (que será la sección 0, índice 14) y el parámetro newIndexPath
para recuperar el objeto para configurar la celda desde el controlador de resultados (que será la sección 0, índice 13).
Supongo que funciona de esta manera porque la eliminación parece haber sucedido ya en cuanto al controlador de resultados, pero no ha sucedido en la vista de tabla (debido a las llamadas beginUpdates/endUpdates
envolviendo las actualizaciones). Tiene sentido si considera el caso anterior, pero parece que toda la documentación no considera este caso.
Así que la respuesta a la pregunta es que parece que debe usar el parámetro indexPath
para recuperar una celda de la vista de tabla, y el parámetro newIndexPath
para recuperar el objeto del controlador de resultados obtenidos. Tenga en cuenta que si no ha habido una inserción o eliminación, parece pasar nil
para newIndexPath
, por lo que en este caso deberá usar indexPath
para ambos fines.
En una reflexión posterior, me parece que NSFetchedController debería llamar al método de delegado con un evento de movimiento en lugar de un evento de actualización. Lo hace en el caso de prueba simple que acabo de crear. Para mí es un misterio en este momento qué condición desencadena una actualización. –
Si leíste el artículo al que me he vinculado en la pregunta, deberías ver que es exactamente lo que hice. – an0
Mi error, en realidad no vi el enlace hasta que lo señaló. ¿Qué línea de código está causando el colapso en su caso? ¿Qué NSIndexPath estás usando y qué haces con él? –
Si un objeto de NSFetchedResultsController cambia y se mueve al "mismo tiempo" -controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:
envía tipo NSFetchedResultsChangeUpdate
(see here).
Mi solución es cambiar el tipo de moverse cada vez que el tipo es actualizar y indexPath no es igual a newIndexPath
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
UITableView *tableView;
if (controller == self.fetchedResultsController) {
tableView = self.tableView;
}
else {
tableView = self.searchDisplayController.searchResultsTableView;
}
// type is "update" ---> should be "move"
if (type == NSFetchedResultsChangeUpdate && [indexPath compare:newIndexPath] != NSOrderedSame && newIndexPath != nil) {
type = NSFetchedResultsChangeMove;
}
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 fetchedResultsController:controller configureCell:(UITableViewCell*)[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationLeft];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationRight];
break;
}
}
Después tiene que actualizar la vista de tabla
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView endUpdates];
[self.tableView reloadData];
}
espero que este ¡es útil!
¿Por qué tienes un reloadData después de un endUpdates? – Frizlab
En ese caso en que el tipo de cambio es "actualizar" pero debe ser "mover", la vista de tabla no se actualiza correctamente. Por lo tanto, debe volver a cargar la vista de tabla. Tal vez no sea necesario en iOS8 y superior, fue en iOS7. –
He estado buscando esta respuesta durante años. Funciona perfecto. Gracias – Nekbeth
- 1. ¿Cómo usar ofuscación para ClickOnce?
- 2. Cómo usar flush() para PrintStream
- 3. Aplicación para iPhone que se bloquea en [self.tableView endUpdates]
- 4. Cómo usar UINib para crear instancias y usar UITableViewCells personalizadas
- 5. ¿Cómo sé cuál es el mejor lugar para usar 'usar'?
- 6. Para usar o no usar expresiones regulares?
- 7. ¿Cómo usar Mockito para probar mensajes SOAP?
- 8. Cómo usar C++ para el servidor apache
- 9. ¿Cómo usar Scala como reemplazo para XSLT?
- 10. ¿Cómo configuro Xcode para usar Maven
- 11. Cómo usar string.Endswith para probar múltiples terminaciones?
- 12. ¿Cómo usar gvim para imprimir diffs?
- 13. ¿Cómo usar EMF para leer archivos XML?
- 14. ¿Cómo usar Moles para un constructor?
- 15. ¿Cómo comenzar a usar Motosierra para Log4j?
- 16. Cómo usar __bridge para ARC correctamente
- 17. ¿Cómo poner Custom ClassLoader para usar?
- 18. Cómo usar git difftool para diferenciar conflictos?
- 19. cómo usar sox para comprimir mp3?
- 20. ¿Cómo usar Lua para el desarrollo web?
- 21. ¿Cómo usar jQuery para paginar datos JSON?
- 22. ¿Cómo usar el violín para depurar?
- 23. Cómo usar CCCrypt() para cifrar un archivo?
- 24. ¿Cómo puedo usar parseInt para un doble?
- 25. Cómo usar SharedAccessSignature para acceder a blobs
- 26. Cómo usar Python/CGI para cargar archivos
- 27. Cómo usar Resources.resx para vincular imágenes
- 28. ¿Cómo usar LiteIDE para un proyecto Go?
- 29. Cómo usar rawQuery para insertar un registro
- 30. ¿Cómo configuro Go para usar un proxy?
¿Cuál es el mensaje de error/stack backtrace? –
newIndexPath está fuera de límite. – an0
Tuve un problema similar, y mi solución/solución alternativa (?) No fue utilizar indexPath/newIndexPath en absoluto para un evento de actualización. Puede ver mi pregunta y la respuesta auto proporcionada aquí: http://stackoverflow.com/questions/11432556/nsrangeexception-exception-in-nsfetchedresultschangeupdate-event-of-nsfetchedres. Por favor, hágamelo saber si ayuda! –