2010-09-05 16 views
7

Cette question est dans le contexte des données de base, mais si je ne me trompe pas, elle s'applique aussi bien à un cas SQL plus général.Comment gérer une table ordonnée avec Core Data (ou SQL) avec des insertions/suppressions?

Je veux maintenir une table ordonnée à l'aide de base de données, avec la possibilité pour l'utilisateur:

  • lignes de Réorganiser
  • insérer de nouvelles lignes partout
  • supprimer toute ligne existante

Quel est le meilleur modèle de données pour cela? Je vois deux façons:

1) Modèle comme un tableau: ajouter un int position propriété à mon entité

2) Modèle comme une liste chaînée: ajouter deux one-to-one relations, next et previous de mon entité se

1), il est facile de trier, mais douloureux pour insérer ou supprimer comme vous devez alors mettre à jour le position de tous les objets qui viennent après

2), il est facile à insérer ou supprimer, mais très difficile à trier. En fait, je ne pense pas savoir comment exprimer un Descripteur de Sort (clause SQL ORDER BY) pour ce cas.

Maintenant, je peux imaginer une variation sur 1):

3) ajouter un int ordering propriété à l'entité, mais au lieu de l'avoir compter un par un, l'ont compte 100 par 100 (par exemple). Ensuite, l'insertion est aussi simple que de trouver n'importe quel nombre entre l'ordre des objets existants précédent et suivant. La renumérotation coûteuse ne doit avoir lieu que lorsque les 100 trous ont été remplis. Faire de cette propriété un flotteur plutôt qu'un int le rend encore meilleur: il est presque toujours possible de trouver un nouveau flotteur à mi-chemin entre deux flotteurs. Suis-je sur la bonne voie avec la solution 3), ou y a-t-il quelque chose de plus intelligent?

Répondre

0

Depuis iOS 5, vous pouvez (et devez) utiliser NSOrderedSet et sa sous-classe modifiable. → Core Data Release Notes for OS X v10.7 and iOS 5.0

Voir la réponse acceptée à How can I preserve an ordered list in Core Data.

+1

Oui. Tu as creusé une vieille question, et tu as raison :-). Malgré quelques problèmes avec NSOrderedSet (qui a une API qui est moins complète que NSArray par exemple) et des relations ordonnées (qui je crois ne sont pas entièrement supportées par les contrôleurs de résultats récupérés). –

+0

Oui, j'ai essayé de faire fonctionner NSFetchedResultsController avec une relation ordonnée. Succès pour la plupart - mais n'a pas réussi à mettre à jour intelligemment la vue de la table, c'est-à-dire à animer l'insertion ou la suppression, au lieu de simplement faire un [tableView reloadData] ... Donc j'ai abandonné les contrôleurs de résultats récupérés liste :-/ –

4

Si la commande est arbitraire, c'est-à-dire qu'elle n'est pas inhérente aux données modélisées, vous n'avez pas d'autre choix que d'ajouter un attribut ou une relation pour maintenir l'ordre.

Je voudrais conseiller la liste liée, car il est plus facile à maintenir. Je ne suis pas sûr de savoir ce que vous entendez par une liste chaînée difficile à trier puisque vous ne serez probablement pas trié sur un ordre arbitraire de toute façon. Au lieu de cela, vous allez simplement chercher l'instance la plus haute et descendre votre chemin.

La commande par un attribut flottant divisible est une bonne idée. Vous pouvez créer un nombre quasi infini d'index intermédiaires simplement en soustrayant l'indice existant inférieur de l'indice existant supérieur, en divisant le résultat par deux et en ajoutant ce résultat à l'indice inférieur.

Vous pouvez également combiner un index divisible avec une liste liée si vous avez besoin d'un ordre pour des tables ou similaires. La liste liée faciliterait la recherche d'index existants et l'index divisible faciliterait le tri si vous en aviez besoin. Les données de base résistent à ce type de commande car elles sont généralement inutiles. Vous ne voulez pas ajouter quelque chose au modèle de données sauf s'il est nécessaire de simuler l'objet, l'événement ou la condition du monde réel décrit par le modèle.Habituellement, l'ordre/le tri ne sont pas inhérents au modèle mais simplement requis par l'interface utilisateur/la vue. Dans ce cas, vous devez avoir la logique de tri dans le contrôleur entre le modèle et la vue.

Réfléchissez bien avant d'ajouter une commande au modèle lorsque vous n'en avez pas besoin.

+0

Si vous utilisez une liste chaînée, comment définissez-vous le descripteur de tri des données de base? Un point d'utilisation des données de base (à savoir un 'NSFetchedResultController') est qu'il vous donnera les résultats d'une requête dans le bon ordre si vous lui fournissez un descripteur de tri. –

+0

L'ordre de tri est inhérent aux données, seulement décidé par l'utilisateur. Pensez par exemple que vous voulez laisser l'utilisateur décider dans quel ordre il veut que ses livres soient mis sur son étagère. Elle pourrait décider de déplacer un livre de la position 7 à la position 14 et 15. Ou vendre le livre en position 12, ou acheter un nouveau livre et l'insérer en position 3. Le lendemain, elle décidera de déplacer ce livre à la toute fin de l'étagère. L'interface utilisateur pour le faire est facile en utilisant un 'UITableView'. Mon problème est avec la meilleure représentation d'une telle "valeur de préférence" pour rendre l'échange/insertion/suppression facile et assez rapide. –

+0

Je pense qu'une liste chaînée combinée à l'index divisible serait la plus rapide. Pour une plus grande vitesse, je déplacerais la commande à une autre entité légère avec une relation à l'entité que vous voulez commander. Faites vos extractions et tris sur l'entité légère, puis chargez l'entité associée selon vos besoins. – TechZen