Périodiquement, tout en travaillant sur les chapitres de données de base dans Plus l'iPhone 3 de développement, Je voudrais actualiser ma copie d'Apple fourni Basés sur la navigation de base de données d'application modèle de projet avec la logique pour gérer différents scénarios courants. Tout en travaillant sur le blog précédents, J'ai fait un peu plus de réglages pour le modèle afin de mieux gérer les changements d'objet qui déclenchent réussi à déplacer des objets entre les sections lorsque vous spécifiez une sectionNameKeyPath. Vous pouvez trouver la version la plus récente de ce modèle de projet here, Et j'ai inclus les quatre méthodes de déléguer à partir du modèle à la fin de ce blog.
J'ai vraiment essayé de donner NSFetchedResultsController le bénéfice du doute. C'est un concept vraiment, vraiment très bien et quand ça marche, je l'aime vraiment, mais l'exécution est bien en dessous niveau normal d'Apple sur la qualité du code. Tout le code que j'ai ajouté à ce modèle est tout simplement nécessaire pour gérer cas d'utilisation typiques supposément pris en charge par cette classe... choses qui doivent être manipulés de la boîte sans avoir besoin de code supplémentaire. Dans ce cas particulier, les méthodes délégué devrait vraiment être seulement nécessaire pour la manipulation des scénarios extraordinaires ou inhabituelles.
Si j'ai le temps, je peut essayer d'encapsuler cette logique dans une sous-classe de NSFetchedResultsController, mais pour le moment, si vous utilisez ce modèle ou les méthodes de déléguer à la fin de cette annonce, il faut prendre soin de la majorité des situations pour vous automatiquement. Je soupçonne qu'il y aura un peu de bricolage à ce code que je l'utilise dans le monde réel de code, mais si il ya, je vais poster les changements et une nouvelle version du modèle ici. En tout cas, ce modèle est un point de départ bien meilleur que modèle fourni d'Apple et peut juste vous empêcher de tirer tous vos cheveux.
J'ai vraiment essayé de donner NSFetchedResultsController le bénéfice du doute. C'est un concept vraiment, vraiment très bien et quand ça marche, je l'aime vraiment, mais l'exécution est bien en dessous niveau normal d'Apple sur la qualité du code. Tout le code que j'ai ajouté à ce modèle est tout simplement nécessaire pour gérer cas d'utilisation typiques supposément pris en charge par cette classe... choses qui doivent être manipulés de la boîte sans avoir besoin de code supplémentaire. Dans ce cas particulier, les méthodes délégué devrait vraiment être seulement nécessaire pour la manipulation des scénarios extraordinaires ou inhabituelles.
Si j'ai le temps, je peut essayer d'encapsuler cette logique dans une sous-classe de NSFetchedResultsController, mais pour le moment, si vous utilisez ce modèle ou les méthodes de déléguer à la fin de cette annonce, il faut prendre soin de la majorité des situations pour vous automatiquement. Je soupçonne qu'il y aura un peu de bricolage à ce code que je l'utilise dans le monde réel de code, mais si il ya, je vais poster les changements et une nouvelle version du modèle ici. En tout cas, ce modèle est un point de départ bien meilleur que modèle fourni d'Apple et peut juste vous empêcher de tirer tous vos cheveux.
- (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];
if (sectionKeyPath == nil)
break;
NSManagedObject *changedObject = [controller objectAtIndexPath:indexPath];
NSArray *keyParts = [sectionKeyPath componentsSeparatedByString:@"."];
id currentKeyValue = [changedObject valueForKeyPath:sectionKeyPath];
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 numberOfRowsInSection:0] == 0)))
[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) {
NSUInteger tableSectionCount = [self.tableView numberOfSections];
NSUInteger frcSectionCount = [[controller sections] count];
if (frcSectionCount >= tableSectionCount)
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:[newIndexPath section]] withRowAnimation:UITableViewRowAnimationNone];
else
if (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;
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