2010-10-12 3 views
1

Je semble rencontrer un problème très étrange qui ne se produit que lorsque vous essayez d'insérer un nouveau NSManagedObject dans une nouvelle section. Fondamentalement mes sections sont des jours et des cellules individuelles sont associées à des temps. Lorsque je DÉPLACE un objet à un jour qui n'a pas actuellement un autre objet (ligne du tableau) associé au jour, la table doit créer une nouvelle section et déplacer la ligne. Au lieu de cela se passe correctement, je reçois ce qui suit:exception levée en essayant d'insérer une nouvelle ligne de table dans la section

Erreur d'application grave. Une exception a été interceptée par le délégué de NSFetchedResultsController lors d'un appel à -controllerDidChangeContent: * - [NSMutableArray removeObjectAtIndex:]: index 1 au-delà des limites [0 .. 0] avec userInfo (null)

Insertion d'un nouvel objet pour une journée qui a actuellement aucun autre objet semble fonctionner très bien.

Le problème semble être quelque part dans ce code, mais je n'arrive pas à comprendre ce qui ne va pas. controller:didChangeSection:... semble être appelé d'abord avec une insertion et une suppression, puis controller:didChangeObject:... est appelée avec NSFetchedResultsChangeMove. Ainsi, l'ordre est:

NSFetchedResultsChangeInsert (en didChangeSection) NSFetchedResultsChangeDelete (en didChangeSection) NSFetchedResultsChangeMove (en didChangeObject)

/** 
Delegate methods of NSFetchedResultsController to respond to additions, removals and so on. 
*/ 

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { 
// The fetch controller is about to start sending change notifications, so prepare the table view for updates. 
[self.plainTableView beginUpdates]; 
} 

- (void)controller:(NSFetchedResultsController *)controller 
    didChangeObject:(id)anObject 
    atIndexPath:(NSIndexPath *)indexPath 
forChangeType:(NSFetchedResultsChangeType)type 
    newIndexPath:(NSIndexPath *)newIndexPath { 
UITableView *tv = self.plainTableView; 

switch(type) { 
    case NSFetchedResultsChangeInsert: 
     [tv insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 

    case NSFetchedResultsChangeDelete: 
     [tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 

    case NSFetchedResultsChangeUpdate: 
     [self configureCell:(UITableViewCell *)[tv cellForRowAtIndexPath:indexPath] atIndexPath:indexPath]; 
     break; 

    case NSFetchedResultsChangeMove: 
     [tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     // Reloading the section inserts a new row and ensures that titles are updated appropriately. 
     [tv reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 
} 
} 

- (void)controller:(NSFetchedResultsController *)controller 
    didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo 
      atIndex:(NSUInteger)sectionIndex 
    forChangeType:(NSFetchedResultsChangeType)type { 
    switch(type) { 
    case NSFetchedResultsChangeInsert: 
     [self.plainTableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 

    case NSFetchedResultsChangeDelete: 
     [self.plainTableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 
} 
} 

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { 
// The fetch controller has sent all current change notifications, so tell the table view to process all updates. 
[self.plainTableView endUpdates]; 
} 

Je pensais que cela était le code du modèle juste norme bien. Est-ce que quelqu'un a une idée de ce qui pourrait être faux?

En fait, il arrive aussi lorsque vous essayez d'insérer une nouvelle ligne dans un jour qui existe déjà, mais pas lors de l'insertion d'une nouvelle ligne/objet pour un jour qui n'existe pas déjà.

Répondre

1

Je pense que vous avez un problème conceptuel ici.

Les méthodes controller:didChange... sont appelées en réponse à une modification du modèle de données détectée par le contrôleur de résultats récupérés (FRC). Je suis assez sûr que votre problème ici est que vous modifiez la table avant ou sans changer les données sous-jacentes.

Les sections et les lignes ne sont pas des attributs de la table, ce sont des attributs des données tels que structurés par la FRC. Si vous devez ajouter une section, vous devez d'abord l'ajouter aux données, puis laisser les méthodes de délégation FRC mettre la table à jour. Le tableau reflète le modèle de données et non l'inverse.

Si vous ne le faites pas de cette façon, le FRC signalera le mauvais nombre de sections ou de lignes et provoquera le crash de la table avec l'erreur que vous avez vue.

+0

Après avoir regardé le code qui semble corriger cela, il semblerait qu'à l'origine je n'avais pas inséré insertRowsAtIndexPaths dans NSFetchedResultsChangeMove. Ainsi, dans NSFetchedResultsChangeMove, la ligne était supprimée mais pas réinsérée ailleurs.Le commentaire dans CoreDataBooks dit "Recharger la section insère une nouvelle ligne et s'assure que les titres sont mis à jour de manière appropriée." Je suppose que cela signifie que l'appel à reloadSections est utilisé pour insérer des lignes, peut-être dans le SDK 3.x. J'ai remarqué que CoreDataBooks a été mis à jour à un moment donné avec un commentaire disant de le rendre compatible avec 4.x – Nimrod

5

Je semble avoir résolu en copiant le code suivant à partir de la dernière version de CoreDataBooks:

case NSFetchedResultsChangeMove: 
     [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 

Avant que le code ici était:

case NSFetchedResultsChangeMove: 
     [tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     // Reloading the section inserts a new row and ensures that titles are updated appropriately. 
     [tv reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 
+0

Oui, la ligne reloadSections plantait aussi la mienne. – RyeMAC3

Questions connexes