Bon, il ya un problème connu avec NSFetchedResultsController lors de l'utilisation des chemins section nom de la clé. Lorsque vous effectuez une modification à un objet existant qui aboutit à une nouvelle section en cours de création, il se bloque. Le délégué du contrôleur de chercher des résultats n'est jamais reçoit la notification d'un insert de la section, ni être notifié sur l'objet se déplaçant entre les sections. Il obtient juste notification que l'objet a été mis à jour.
Je me suis battu avec NSFetchedResultsController depuis un certain temps maintenant, mais cet après-midi, je pense que j'en ai fait ma chienne. Vous pouvez réellement gérer cette situation, si elle exige un peu de code gnarley. Je vais mettre à jour la navigation basé sur base du modèle de projet Application Data Xcode sous peu avec cette logique, mais voici comment vous gérer ce problème dans les méthodes des résultats récupérés déléguée contrôleur. Plus précisément regarder la déclaration de cas NSFetchedResultsChangeUpdate dans le contrôleur: didChangeObject: atIndexPath: forChangeType: newIndexPath:. Là, nous déterminons si le chemin de clé la section nom a changé, et si elle a, nous déterminons si nous devons ajouter une nouvelle section à la table. Ensuite, nous tombons dans tot qu'il NSFetchedResultsChangeMove et suivre la même logique.
Une mise en garde, cependant, je ne sais pas si cela va fonctionner avec des chemins nom de la section clés qui utilisent des clés imbriquées (par exemple "foo.bar"). En fait, je suis sûr que ça ne marchera pas, mais je vais regarder de fixation un peu plus tard. Pour la grande majorité des situations, cela devrait colmater le problème section NSFetchedResultsController assez bien.
Le code a été fixé pour soutenir les touches imbriqué dans le chemin de clé de noms des sections.
Je me suis battu avec NSFetchedResultsController depuis un certain temps maintenant, mais cet après-midi, je pense que j'en ai fait ma chienne. Vous pouvez réellement gérer cette situation, si elle exige un peu de code gnarley. Je vais mettre à jour la navigation basé sur base du modèle de projet Application Data Xcode sous peu avec cette logique, mais voici comment vous gérer ce problème dans les méthodes des résultats récupérés déléguée contrôleur. Plus précisément regarder la déclaration de cas NSFetchedResultsChangeUpdate dans le contrôleur: didChangeObject: atIndexPath: forChangeType: newIndexPath:. Là, nous déterminons si le chemin de clé la section nom a changé, et si elle a, nous déterminons si nous devons ajouter une nouvelle section à la table. Ensuite, nous tombons dans tot qu'il NSFetchedResultsChangeMove et suivre la même logique.
Une mise en garde, cependant, je ne sais pas si cela va fonctionner avec des chemins nom de la section clés qui utilisent des clés imbriquées (par exemple "foo.bar"). En fait, je suis sûr que ça ne marchera pas, mais je vais regarder de fixation un peu plus tard. Pour la grande majorité des situations, cela devrait colmater le problème section NSFetchedResultsController assez bien.
Le code a été fixé pour soutenir les touches imbriqué dans le chemin de clé de noms des sections.
- (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:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate: {
NSString *sectionKeyPath = [controller sectionNameKeyPath];
NSManagedObject *changedObject = [controller objectAtIndexPath:indexPath];
NSArray *keyParts = [sectionKeyPath componentsSeparatedByString:@"."];
id currentKeyValue = [changedObject valueForKeyPath:sectionKeyPath];
// If nested keys, need to get the related object to get
// the committed key value
for (int i = 0; i < [keyParts count] - 1; i++) {
NSString *onePart = [keyParts objectAtIndex:i];
changedObject = [changedObject valueForKey:onePart];
}
sectionKeyPath = [keyParts lastObject];
NSDictionary *committedValues = [changedObject committedValuesForKeys:nil];
if ([[committedValues valueForKeyPath:sectionKeyPath] isEqual:currentKeyValue])
break;
NSUInteger tableSectionCount = [self.tableView numberOfSections];
NSUInteger frcSectionCount = [[controller sections] count];
if (tableSectionCount != frcSectionCount) {
// Need to insert a section
NSArray *sections = controller.sections;
NSInteger newSectionLocation = -1;
for (id oneSection in sections) {
NSString *sectionName = [oneSection name];
if ([currentKeyValue isEqual:sectionName]) {
newSectionLocation = [sections indexOfObject:oneSection];
break;
}
}
if (newSectionLocation == -1)
return; // uh oh
if (!(newSectionLocation == 0 && tableSectionCount == 1))
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:newSectionLocation] withRowAnimation:UITableViewRowAnimationFade];
NSUInteger indices[2] = {newSectionLocation, 0};
newIndexPath = [[[NSIndexPath alloc] initWithIndexes:indices length:2] autorelease];
}
}
case NSFetchedResultsChangeMove:
if (newIndexPath != nil) {
[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;
default:
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 NSFetchedResultsChangeMove:
break;
case NSFetchedResultsChangeUpdate:
break;
default:
break;
}
}
Aucun commentaire:
Enregistrer un commentaire