2010-01-08 18 views
5

Tengo algunos problemas con core data/NSFetchedResultsController. No estoy del todo seguro de dónde está el error, ya que el mensaje es bastante vago.Core data/NSFetchedResultsController error

Tengo un problema con la inserción de más de un objeto cuando el controlador de resultados obtenidos no tiene objetos recuperados. El siguiente código se bloqueará con el siguiente error si intento insertar varios objetos sin recuperar ninguno. No se cuelga si lo uso para insertar un objeto, y no se cuelga si ya hay objetos recuperados.

El bloqueo se produce en el método de guardar. títulos en un NSArray y en este ejemplo contiene 5 cadenas.

Error grave de la aplicación. Excepción fue capturado durante el cambio de Datos Básicos procesamiento: * - [NSCFArray objectAtIndex:]: índice (4) más allá de límites (1) con userInfo (nulo) * Terminación de aplicación debido a excepción no detectada 'NSRangeException', razón : '*** - [NSCFArray objectAtIndex:]: índice (4) más allá de los límites (1)'

NSEnumerator *titleEnumerator = [titles objectEnumerator]; 
NSString *title; 
NSMutableArray *tasks = [NSMutableArray array]; 
Todo *todo; 

while(title = [titleEnumerator nextObject]) 
{ 
    todo = (Todo *)[NSEntityDescription insertNewObjectForEntityForName:@"Todo" inManagedObjectContext:managedObjectContext]; 
    todo.title = title; 
    todo.state = [NSNumber numberWithInteger:TodoStateIncomplete]; 
    todo.priority = [NSNumber numberWithInteger:TodoPriorityNormal]; 
    todo.timeStamp = [NSDate date]; 
    todo.dueDate = [NSDate distantFuture]; 
} 

NSError *error; 

if(![managedObjectContext save:&error]) 
{ 
    NSLog(@"Unresolved error %@ %@", error, [error userInfo]); 
    abort(); 
} 
+0

he logrado conseguir alrededor del accidente con un poco de un truco poco fiables. En el ciclo, verifico si es la primera vez. Si es que guardo. Esto actúa como si solo estuviera agregando un objeto al principio, lo que evita que se bloquee cuando agrego muchos. Esto me ayudará pero me gustaría saber por qué sucede esto, así puedo solucionarlo correctamente. –

Respuesta

5

He aquí un consejo de Marcus Zarra (autor del libro de Core Data):

Core Data error when deleting row in tableView

"Trate de dividir en objc_exception_throw y ver qué método está lanzando la excepción. Eso debería ayudar a rastrearlo "

+0

Siguiendo el consejo de Marcus (¡otra vez!), Esto me recordó la entrada del blog de Jeff Lamarche para una versión actualizada de la muestra de datos básicos basados ​​en navegación de Apple: http://iphonedevelopment.blogspot.com/2010/01/navigation -base-core-data-application.html – petert

0

Sé que es poco probable que sea la respuesta, pero dado que el bloqueo se produce al guardar: y recuerdo haber tenido un error extraño con esta vez ... El error que tuve fue corregido Así, calculo que vale la pena un tiro.

por lo tanto, dicho esto, trate de cambiar

NSError *error; 

a

NSError *error = nil; 
+1

Si bien esto siempre es un buen consejo, no es útil en este caso porque su código está verificando la respuesta desde el guardado y ** luego ** mostrando el error. En ese caso, el error siempre se completará. –

4

errores como éste en un Core Data ahorrar al usar el iPhone SDK generalmente apuntan a un error en los métodos delegados NSFetchedResultsController. Específicamente, uno de los ejemplos de código de Apple es incorrecto y con frecuencia produce este error. Sugeriría mirar sus métodos de delegado y compararlos con el código de ejemplo más reciente, ya que puede encontrar que Apple ha actualizado el código de ejemplo en la documentación y si vuelve a copiar su código, este error puede desaparecer.

Espero que ayude.

+1

¿Tiene un enlace a un código de ejemplo que funcione? – Gujamin

+0

El ejemplo que se incluye en Apple Docs ahora (3 años después) es correcto. Sugeriría usarlo. –

+0

Enlace por favor? Si miramos el código de ejemplo, hay varios en Core Data que no mencionan específicamente NSFetchedResultsController, por lo que no estoy seguro de qué ejemplo se verifica que funcione. – Gujamin

0

En mi caso esta implementación fue útil (petert de agradecimiento):

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller{ [self.tableView beginUpdates]; } 

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller{ 
    [self.tableView endUpdates];} 

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath{ 
switch (type) { 
    case NSFetchedResultsChangeInsert: 

     [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 
     break; 

    case NSFetchedResultsChangeDelete: 
     [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 
     break; 

    case NSFetchedResultsChangeUpdate: { 

     NSString *sectionKeyPath = [controller sectionNameKeyPath]; 
     if (sectionKeyPath == nil){ 
      break; 
     } 

     [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone]; 

     break; 
    } 
    case NSFetchedResultsChangeMove: { 

     if (newIndexPath != nil) { 

      NSUInteger tableSectionCount = [self.tableView numberOfSections]; 
      NSUInteger frcSectionCount = [[controller sections] count]; 
      if (frcSectionCount > tableSectionCount) 
       [self.tableView insertSections:[NSIndexSet indexSetWithIndex:[newIndexPath section]] withRowAnimation:UITableViewRowAnimationNone]; 
      else if (frcSectionCount < tableSectionCount && tableSectionCount > 1) 
       [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:[indexPath section]] withRowAnimation:UITableViewRowAnimationNone]; 


      [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      [self.tableView insertRowsAtIndexPaths: [NSArray arrayWithObject:newIndexPath] 
            withRowAnimation: UITableViewRowAnimationRight]; 

     } 
     else { 
      [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:[indexPath section]] withRowAnimation:UITableViewRowAnimationFade]; 
     } 
     break; 
    } 
}} 
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id<NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type{ 
switch (type) { 
    case NSFetchedResultsChangeInsert: 
     if (!((sectionIndex == 0) && ([self.tableView numberOfSections] == 1))) 
      [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 
    case NSFetchedResultsChangeDelete: 
     if (!((sectionIndex == 0) && ([self.tableView numberOfSections] == 1))) 
      [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; 

     break; 
    case NSFetchedResultsChangeUpdate: 
     break; 
    case NSFetchedResultsChangeMove: 
     break; 
}} 
+0

Y gracias a JEFF LAMARCHE http://iphonedevelopment.blogspot.de/2010/01/navigation-based-core-data-application.html –