web-dev-qa-db-fra.com

Comment trier les propriétés extraites de Core Data

Le Core Data Documentation indique que:

La demande d'extraction associée à la propriété [fetched] peut avoir un ordre de tri, et ainsi la propriété extraite peut être ordonnée.

Comment spécifier les descripteurs de tri pour la propriété extraite dans l'éditeur de modèle de données de Xcode? Je ne trouve aucun champ pertinent nulle part. Je développe pour la plate-forme iPhone, si cela fait une différence.

Si cela n'est pas possible via l'éditeur de modèle graphique, comment puis-je modifier la demande d'extraction de la propriété extraite dans le code afin qu'elle comporte un descripteur de tri?

20
Daniel Dickison

L'outil de modélisation ne semble pas avoir le moyen de définir les descripteurs de tri sur la demande d'extraction.

Après le chargement du modèle, mais avant de l'associer à un coordinateur de magasin persistant, il devrait être possible [1] de rechercher les descriptions de propriété extraites pour lesquelles vous souhaitez contrôler l'ordre de tri et de remplacer leurs requêtes d'extraction par des requêtes d'extraction triées. descripteurs mis sur eux.

[1] En principe, cela devrait fonctionner. En pratique, je ne l’ai ni fait ni testé.

5
Jim Correia

Vous pouvez réellement récupérer la propriété extraite du modèle et y ajouter les descripteurs de tri (encore une fois, dans le code). Je l'ai fait dans la méthode standard que XCode génère dans votre AppDelegate si vous choisissez l'un des modèles avec Core Data:

Au fait. Cela trie TOUTES les propriétés extraites sur TOUS les modèles de votre modèle de données. Vous pouvez l'adapter et l'adapter à votre imagination, mais c'était le moyen le plus succinct de gérer le tri des 7 modèles distincts, chacun contenant des propriétés extraites qu'il convenait de trier par nom. Fonctionne bien.

/**
 Returns the managed object model for the application.
 If the model doesn't already exist, it is created by merging all of the models found in the application bundle.
 */
- (NSManagedObjectModel *)managedObjectModel {

    if (managedObjectModel != nil) {
        return managedObjectModel;
    }
    managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];    

    // Find the fetched properties, and make them sorted...
    for (NSEntityDescription *entity in [managedObjectModel entities]) {
        for (NSPropertyDescription *property in [entity properties]) {
            if ([property isKindOfClass:[NSFetchedPropertyDescription class]]) {
                NSFetchedPropertyDescription *fetchedProperty = (NSFetchedPropertyDescription *)property;
                NSFetchRequest *fetchRequest = [fetchedProperty fetchRequest];

                // Only sort by name if the destination entity actually has a "name" field
                if ([[[[fetchRequest entity] propertiesByName] allKeys] containsObject:@"name"]) {
                    NSSortDescriptor *sortByName = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
                    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortByName]];
                    [sortByName release];
                }
            }
        }
    }

    return managedObjectModel;
}
35
Tim Shadel

Vous ne les spécifiez pas dans l'éditeur graphique (pour autant que je sache).

Vous les spécifiez dans le code où vous effectuez l'extraction.

NSFetchRequest* request = [[NSFetchRequest alloc] init];
NSEntityDescription* entity = [NSEntityDescription entityForName:@"whatYouAreLookingFor"
    inManagedObjectContext:self.managedObjectContext];
[request setEntity:entity];

// here's where you specify the sort
NSSortDescriptor* sortDescriptor = [[NSSortDescriptor alloc]
                                initWithKey:@"name" ascending:YES];
NSArray* sortDescriptors = [[[NSArray alloc] initWithObjects: sortDescriptor, nil] autorelease];
[request setSortDescriptors:sortDescriptors];
[sortDescriptor release];

fetchedResultsController = [[NSFetchedResultsController alloc]
               initWithFetchRequest:request
               managedObjectContext:self.managedObjectContext
                 sectionNameKeyPath:nil
                          cacheName:@"myCache"];
13
mmc

En utilisant l'excellente réponse de Tim Shadel, j'ai ajouté le tri par sous-classe NSManagedObject ...

... dans Tier.m (qui est une sous-classe NSManagedObject) ...

+ (void)initialize
{
    if(self == [Tier class])
    {
        NSFetchedPropertyDescription *displayLessonPropertyDescription = [[[Tier entityDescription] propertiesByName] objectForKey:@"displayLesson"];
        NSFetchRequest *fetchRequest = [displayLessonPropertyDescription fetchRequest];

        NSSortDescriptor *sortByName = [[NSSortDescriptor alloc] initWithKey:@"displayOrder" ascending:YES];
       [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortByName]];
        [sortByName release];
    }
}
5
rob5408

Malheureusement, la capacité de trier est quelque peu limitée. Par exemple, vous ne pouvez pas prendre un champ qui est une chaîne NSString contenant un nombre et le trier numériquement, du moins pas avec un magasin de support SQLite. Tant que vous triez alphabétiquement des chaînes, numériquement, des valeurs stockées sous forme de nombres, etc., le NSSortDescriptor appliqué à la demande d'extraction fonctionne parfaitement.

0
Jeff Medcalf

Pour une seule propriété extraite, Swift 4, Xcode 9.4:

// retrieve the fetched property's fetch request    
let fetchedPropertyRequest = (modelName.entitiesByName["entityName"]!.propertiesByName["fetchedPropertyName"] as! NSFetchedPropertyDescription).fetchRequest

// set up the sort descriptors
let sortDescriptors = [NSSortDescriptor(key: "keyName", ascending: true)]

// add the sort descriptors to the fetch request
fetchedPropertyRequest!.sortDescriptors = sortDescriptors

Voici la même chose la manière de loooonnnnnngggggggg:

// retrieve the fetched property's fetch request
let theEntityDescription: NSEntityDescription = modelName.entitiesByName["entityName"]!
let theFetchedPropertyDescription = theEntityDescription.propertiesByName["fetchedPropertyName"]! as! NSFetchedPropertyDescription
let theFetchedPropertyRequest = theFetchedPropertyDescription.fetchRequest

// set up the sort descriptors
let sortDescriptor1 = NSSortDescriptor(key: "keyName", ascending: true)
let theSortDescriptors = [sortDescriptor1]

// add the sort descriptors to the fetch request
theFetchedPropertyRequest!.sortDescriptors = theSortDescriptors

Remarque: pour cet exemple, je force les valeurs non emballées. Assurez-vous de prendre en compte les valeurs optionnelles dans votre code actuel!

0
leanne

Mettez ceci dans votre sous-classe NSManagedObject:

+ (void)initialize
{
    if (self != [EntityManagedObjectSubClass class]) return;
    NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
    NSEntityDescription *entityDescription = [managedObjectModel entitiesByName][@"entityName"];
    NSFetchedPropertyDescription *fetchedPropertyDescription = [entityDescription propertiesByName][@"fetchedPropertyName"];
    NSFetchRequest *fetchRequest = [fetchedPropertyDescription fetchRequest];
    NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"sortDescriptorKey" ascending:YES];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
}

Remplacez EntityManagedObjectSubClass, entityName, fetchedPropertyName et sortDescriptorKey par vos propres commandes.

0
Rudolf Adamkovič