Avez-vous rechargé la vue de table après avoir effectué la récupération à nouveau?
Cela a fonctionné pour moi:
self.fetchedResultsController = nil;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(@"Error in refetch: %@",[error localizedDescription]);
abort();
}
[self.tableView reloadData];
MISE À JOUR
Le contrôleur tiré par les cheveux de résultats est observer les choses objets pour les changements, pas des objets de domaine. Puisque nous modifions l'objet Compte sur un domaine, il est logique que le contrôleur de résultats récupérés ne soit pas mis à jour (à l'exception de la nouvelle chose).
La solution idéale serait un moyen de dire au contexte d'objet géré ou au contrôleur de résultats récupérés que les choses exactes ont "changé" (boucle sur les choses du domaine qui avaient précédemment le compte), mais ce serait toujours un processus manuel.
L'alternative est d'effectuer de nouveau chercher et de recharger la table qui a fonctionné pour moi.
J'ai créé ce modèle en fonction de votre description:
compte < ---> Domaine < --- >> Chose
Pour tester cela, j'ai créé choses "One" et "Deux" en Domaine domainOne et Things "Three", "Four" et "Five" dans Domain domainTwo. domainOne a le compte alors que domainTwo n'a pas de compte.
Lorsque l'application est chargée, la vue de table affiche les éléments "One" et "Two" comme prévu.
Quand je tape "Change", domainTwo se voit attribuer le compte et domainOne perd son compte. En outre, une nouvelle chose nommée "Six" est créée dans domainTwo.
Chose "Six" apparaît avec "Un" et "Deux" même s'ils ne répondent plus au prédicat. Cela correspond au problème que vous décrivez.
Puis, je tape "Refetch" et la table se recharge avec "Three", "Four", "Five" et "Six". C'est le comportement désiré.
Voici le code du contrôleur de vue pertinent:
- (void)addTestData {
account = [NSEntityDescription insertNewObjectForEntityForName:@"Account" inManagedObjectContext:self.managedObjectContext];
domainOne = [NSEntityDescription insertNewObjectForEntityForName:@"Domain" inManagedObjectContext:self.managedObjectContext];
domainTwo = [NSEntityDescription insertNewObjectForEntityForName:@"Domain" inManagedObjectContext:self.managedObjectContext];
[domainOne setValue:account forKey:@"domainCurrentAccount"];
NSArray *thingNames = [NSArray arrayWithObjects:@"One", @"Two", @"Three", @"Four", @"Five", nil];
for (NSString *name in thingNames) {
NSManagedObject *thing = [NSEntityDescription insertNewObjectForEntityForName:@"Thing" inManagedObjectContext:self.managedObjectContext];
[thing setValue:name forKey:@"thingName"];
if (name == @"One" || name == @"Two") {
[thing setValue:domainOne forKey:@"thingDomain"];
} else {
[thing setValue:domainTwo forKey:@"thingDomain"];
}
}
}
- (void)change {
[domainTwo setValue:account forKey:@"domainCurrentAccount"];
[domainOne setValue:nil forKey:@"domainCurrentAccount"];
NSManagedObject *thing = [NSEntityDescription insertNewObjectForEntityForName:@"Thing" inManagedObjectContext:self.managedObjectContext];
[thing setValue:@"Six" forKey:@"thingName"];
[thing setValue:domainTwo forKey:@"thingDomain"];
}
- (void)refetch {
self.fetchedResultsController = nil;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(@"Error in refetch: %@",[error localizedDescription]);
abort();
}
[self.tableView reloadData];
}
- (void)viewDidLoad {
[super viewDidLoad];
UIBarButtonItem *changeButton = [[UIBarButtonItem alloc] initWithTitle:@"Change" style:UIBarButtonItemStyleBordered target:self action:@selector(change)];
self.navigationItem.leftBarButtonItem = changeButton;
[changeButton release];
UIBarButtonItem *refetchButton = [[UIBarButtonItem alloc] initWithTitle:@"Refetch" style:UIBarButtonItemStyleBordered target:self action:@selector(refetch)];
self.navigationItem.rightBarButtonItem = refetchButton;
[refetchButton release];
[self addTestData];
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
J'ai essayé sans effet.Cela ne devrait pas être nécessaire, car le contrôleur de résultats récupéré surveille tous les changements sur le MOC et effectue toutes les autres mises à jour de table dont il a besoin sur sa collection. Recharger les vues de table est un dernier recours car il n'est pas animé et tue toute animation en cours. –
J'ai expliqué pourquoi cela ne fonctionnait pas comme prévu et ajouté des détails pour ma solution originale qui fonctionne. – gerry3
Intéressant, mais il y a une différence clé dans votre code: dans le mode de récupération, vous jetez le contrôleur de résultat récupéré en cours et en créez un nouveau. Je demande spécifiquement d'utiliser le même contrôleur et de lui demander de faire un autre chargement, ce que j'avais supposé, en le faisant réévaluer toutes les entités par rapport au prédicat. Il est possible que cela ne fasse rien, mais les docs ne le disent pas. Récupérer peut être un événement ponctuel et une fois qu'il a des résultats, plus besoin d'aller chercher. Il n'y a pas de "dénouer" pour jeter les résultats qu'il a. –