Quelque part, je n'ai jamais posté ma dose finale pour les problèmes NSFetchedResultsController diverses. J'ai soumis un rapport de bug à Apple pour obtenir le rang les chiffres réels de NSFetchedResultsController y compris tout différé insertions et des suppressions, mais est allé de l'avant avec l'élaboration d'une solution de contournement qui permet de suivre les inserts et supprime localement. Je pensais avoir posté cette information, mais je suppose que je n'ai jamais fait (désolé). Je suis optimiste que ces questions seront fixés en 3.2, mais qui n'ont pas eu le temps de vraiment lancer la nouvelle version de NSFetchedResultsController à l'épreuve, et même si je l'avais, le NDA me garder d'être en mesure de vous dire ce que j'avais trouvé. Néanmoins, le fait qu'il a été mis à jour qui me rend optimiste que cette solution est temporaire et que Apple a finalement livré une version prête pour la production d'NSFetchedResultsController. En attendant ...
Je vais donner le change dans le contexte du chapitre 7 de l'application Plus l'iPhone 3 de développement, Mais ces changements sont génériques et peuvent seulement être copiés sur tout projet utilisant une NSFetchedResultsController et les méthodes délégué du chapitre 2. Je n'ai pas l'habitude d'encourager copier-coller de codage, mais pour une solution de contournement temporaire, il fait sens.
In HeroListViewController.h, Nous devons ajouter une variable d'instance de garder une trace des inserts reportés et supprime:
Ensuite, nous avons besoin de faire quelques changements à deux des méthodes déléguées NSFetchedResultsController. Chose la plus facile est de probablement juste de remplacer la version existante avec ces nouvelles versions. La seule différence avec la version précédente est que nous gardons la trace des insertions et des suppressions pour chaque transaction et utiliser ensuite le nombre de lignes pour les sections est déterminé en ajoutant le différé d'insertion / délétion comptent au nombre rapporté par le NSFetchedResultsController:
Vous pouvez trouver la version fixe du chapitre 7 de demande ici.
Je vais donner le change dans le contexte du chapitre 7 de l'application Plus l'iPhone 3 de développement, Mais ces changements sont génériques et peuvent seulement être copiés sur tout projet utilisant une NSFetchedResultsController et les méthodes délégué du chapitre 2. Je n'ai pas l'habitude d'encourager copier-coller de codage, mais pour une solution de contournement temporaire, il fait sens.
In HeroListViewController.h, Nous devons ajouter une variable d'instance de garder une trace des inserts reportés et supprime:
#import <UIKit/UIKit.h>
#define kSelectedTabDefaultsKey @"Selected Tab"
enum {
kByName = 0,
kBySecretIdentity,
};
@class ManagedObjectEditor;
@interface HeroListViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, UITabBarDelegate, UIAlertViewDelegate, NSFetchedResultsControllerDelegate>{
UITableView *tableView;
UITabBar *tabBar;
ManagedObjectEditor *detailController;
@private
NSFetchedResultsController *_fetchedResultsController;
NSUInteger sectionInsertCount;
}
@property (nonatomic, retain) IBOutlet UITableView *tableView;
@property (nonatomic, retain) IBOutlet UITabBar *tabBar;
@property (nonatomic, retain) IBOutlet ManagedObjectEditor *detailController;
@property (nonatomic, readonly) NSFetchedResultsController *fetchedResultsController;
- (void)addHero;
- (IBAction)toggleEdit;
@end
Ensuite, nous avons besoin de faire quelques changements à deux des méthodes déléguées NSFetchedResultsController. Chose la plus facile est de probablement juste de remplacer la version existante avec ces nouvelles versions. La seule différence avec la version précédente est que nous gardons la trace des insertions et des suppressions pour chaque transaction et utiliser ensuite le nombre de lignes pour les sections est déterminé en ajoutant le différé d'insertion / délétion comptent au nombre rapporté par le NSFetchedResultsController:
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
sectionInsertCount = 0;
[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 + sectionInsertCount != 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];
sectionInsertCount++;
}
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 + sectionInsertCount) {
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:[newIndexPath section]] withRowAnimation:UITableViewRowAnimationNone];
sectionInsertCount++;
}
[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];
sectionInsertCount++;
}
break;
case NSFetchedResultsChangeDelete:
if (!((sectionIndex == 0) && ([self.tableView numberOfSections] == 1) )) {
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
sectionInsertCount--;
}
break;
case NSFetchedResultsChangeMove:
break;
case NSFetchedResultsChangeUpdate:
break;
default:
break;
}
}
Vous pouvez trouver la version fixe du chapitre 7 de demande ici.
Aucun commentaire:
Enregistrer un commentaire