3

Je rencontre actuellement un problème où mon UITableViewController/UITableView qui utilise un NSFetchedResultsController affiche environ 86 éléments lorsque le fetchLimit sur le fetchRequest pour le FRC est 4. Je sais que 86 éléments satisfont le fetch lui-même, et je sais que la raison pour laquelle ils apparaissent est parce que le didChangeObject: atIndexPath ... est appelé pour chacun des 86, et j'insère comme est le type de l'implémentation par défaut.objectAtIndex: 0] numberOfObjects]> fetchLimit

Ma question est la suivante: pourquoi fetchLimit ne limite-t-il pas le nombre d'objets que le NSFetchedResultsController essaie de "changer" (insérer dans ce cas)?

Mon cas d'utilisation d'application est que le premier onglet affiche les éléments de flux typiques que je reçois (sur un thread secondaire) au lancement de l'application. Je les sauvegarde dans CoreData sur un contexte séparé, qui finit par fusionner avec le contexte du thread principal et initie les rappels FRC pour ce qui a changé. Ma question concerne spécifiquement le cas initial où aucun élément n'existe.


Voici mon fetchRequest:

NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease]; 
fetchRequest.entity = [NSEntityDescription entityForName:ENTITY_CONTENT_ITEM inManagedObjectContext:managedObjectContext]; 

// Set a limit on the number of items returned 
[fetchRequest setFetchLimit:4]; 

// Set a Predicate to limit the fetch to featured items only 
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"featured == YES AND contentType == %d", contentType]]; 

// Set the sort descriptors 
NSSortDescriptor *sortDateDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"sortDate" ascending:NO] autorelease]; 
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortDateDescriptor]]; 

Le contentType ci-dessus est tout simplement un moyen de sortir ce qui est censé afficher dans cet onglet par rapport aux autres onglets. En vedette est une propriété booléenne sur l'élément, qui ressemble plus à un interrupteur sur à des fins d'affichage.

Voici mon didChangeObject:

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { 
    switch(type) { 
    case NSFetchedResultsChangeInsert: 
     [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 
    case NSFetchedResultsChangeDelete: 
     [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 
    case NSFetchedResultsChangeUpdate: 
     [tableView cellForRowAtIndexPath:indexPath]; 
     break; 
    case NSFetchedResultsChangeMove: 
     [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     // Reloading the section inserts a new row and ensures that titles are updated appropriately. 
     [tableView reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 
    } 
} 

Je sais que ça va être difficile de répondre à cette question, mais même une explication de la façon dont la CRF décide combien de fois appeler didChangeObject serait vraiment utile.

Répondre

1

https://devforums.apple.com/thread/60319?tstart=0

Pour ceux qui ne peuvent y accéder, vérifier. Le développeur Apple fournit un bon résumé rapide des modifications apportées à la pile CoreData/NSFetchedResultsController/UITableViewController dans iOS4.0.

Des modifications ont été apportées aux versions 3.2 et 4.0 pour améliorer la mise en cache et les performances, ainsi que pour résoudre les problèmes connus. La mise en cache persistante est beaucoup plus agressive, et les utilisateurs abusant du cacheName ont donc des problèmes. Définir cacheName sur nil à la place, ou nettoyer l'utilisation et appeler + deleteCacheWithName lorsque cela est approprié sont des solutions à cela. Le recalcul de la section a été amélioré pour effectuer plus de calculs via la base de données au lieu d'en mémoire chaque fois que possible. Les déclenchements de sectionnement chaque fois que le cache est reconstruit (ou si vous n'utilisez pas de cache, lorsque performFetch est appelé). La solution de contournement .description fait que le keypath fait référence à une propriété non modélisée (la méthode -description) qui fait que le calcul de la section fonctionne en mémoire car la base de données ne connaît rien à propos de -description.

Dans 4.0, il y avait également des modifications apportées à UITableView pour résoudre un certain nombre de problèmes impliquant les rappels de délégué UITableViewController. Les personnes devant utiliser -reloadData sur des versions antérieures d'iOS pour contourner les problèmes devraient pouvoir utiliser les rappels plus fins sur iOS4.

-BenT (Apple)

Étant donné que, j'ai ajouté à mon .description sectionNameKeyPath dans mon appel fetchedResultsController initWithFetchRequest. Cela fait apparemment que le calcul de la section a lieu en mémoire et non sur le disque, ce qui a corrigé un problème avec mes sections pensant qu'elles avaient plus d'objets qu'elles n'en avaient.

Cela fonctionne pour 4.0, et dans 3.0 je viens d'appeler reloadData dans le callback controllerDidChangeContent. N'hésitez pas à me tirer un message si vous avez des problèmes similaires.

Questions connexes