2011-05-02 3 views
0

J'ai une application Cocoa Mac avec un champ de recherche et une vue de collection liée à une table sqlite via CoreData. La table contient plusieurs centaines de milliers d'enregistrements avec des champs de texte (nom, lieu, ...) indexés par nom. J'utilise le prédicat BEGINSWITH dans une liaison de champ de recherche pour sélectionner une douzaine d'enregistrements à afficher dans une vue de collection. Tout fonctionne bien, mais le problème est que CoreData charge la totalité de la table en mémoire lors de la première demande de requête et ne fait ensuite que le filtrage nécessaire des enregistrements pour l'affichage, ce qui signifie un retard considérable pour l'utilisateur.CoreData et grandes tables

Existe-t-il un moyen de configurer CoreData afin que la table entière ne se charge pas dans la mémoire? Idéalement, je voudrais chercher seulement les 100 premiers éléments d'une gamme d'enregistrements triés par ordre alphabétique pour chaque requête dans le champ de recherche.

+2

Quelques conseils. Vous n'avez pas "une vue de collection liée à une table sqlite via CoreData." Les données de base ne sont pas SQL. Les entités ne sont pas des tables. Les objets ne sont pas des lignes. Les attributs ne sont pas des colonnes. Les relations ne sont pas des jointures. Core Data est un système de gestion de graphe d'objet qui peut ou non persister dans le graphe d'objets et peut ou non utiliser SQL loin derrière la scène pour le faire. Si vous essayez de penser aux données de base en termes SQL, vous risquez de vous méprendre complètement sur les données de base et de perdre beaucoup de temps et de temps. – TechZen

+0

Qu'est-ce qui vous fait penser que "CoreData charge toute la table en mémoire à la première requête ..."? Les données de base ne fonctionnent pas comme ça. Supposons-nous simplement que l'application est lente? – TechZen

+0

@TechZen: Je comprends votre point. Mon problème est que mon application triviale est lente au démarrage. J'ai essayé de comprendre ce qui se passait en mettant des loggings de débogage dans une méthode NSArrayController fetchWithRequest et j'ai découvert que toute la table est effectivement chargée dans le contrôleur de tableau à la première requête, mais je veux seulement afficher les 100 premiers enregistrements ma vue de collection. Je suis nouveau à Cocoa et je suis sûr que c'est juste une question de configuration incorrecte. J'apprécie tout indice qui pourrait me diriger dans la bonne direction. – mschuster

Répondre

2

Sur iOS, ceci serait réalisé en utilisant un NSFetchedResultsController. La question suivante décrit les contrôleurs équivalents Mac (tels que NSArrayController): NSFetchedResultsController Mac OSX Cocoa equivalent.

EDIT

Selon mon commentaire ci-dessous, un NSFetchRequest devrait être créé conjointement avec le contrôleur RAID. Cela peut ensuite être configuré avec fetchLimit et fetchOffset pour déterminer combien de résultats d'extraction sont renvoyés.

+0

Oui, j'ai utilisé NSArrayController. Le problème est qu'il est rempli avec une requête: sélectionnez le nom de mytable; qui est plus de 100k enregistrements. Je voudrais l'avoir peuplé avec quelque chose comme: sélectionner le nom de mytable où le nom comme 'j%' commander par nom limite 100; afin que le contrôleur de baie ne transporte que les entrées réellement affichées dans ma vue de collection. – mschuster

+2

@mschuster: Pour limiter le nombre de résultats renvoyés, configurez votre NSArrayController pour utiliser NSFetchRequest. Vous pouvez sous-classer votre 'NSArrayController' et remplacer la méthode' fetchWithRequest: merge: error: '. Votre 'NSFetchRequest' peut être configuré avec' fetchLimit' et 'fetchOffset' pour déterminer combien de résultats devraient être retournés par le fetch. – Stuart

+0

+ 1 un contrôleur de matrice ne doit récupérer et ne pas détecter les objets gérés réellement nécessaires à l'affichage immédiat de la tableview. La définition de fetchLimit, etc, aide encore plus, même si dans mon expérience, il est rarement nécessaire avec un contrôleur de tableau. – TechZen

0

Assurez-vous que l'ensemble de requêtes d'extraction est défini comme erreurs uniquement. De cette façon, seuls les objets dont les attributs sont activement accessibles seront entièrement chargés en mémoire.

Questions connexes