2009-08-19 5 views
26

J'ai deux modèles Département et travailleur. Les ministères ont beaucoup de relations (travailleurs) avec les travailleurs. Le travailleur a un champ firstName. Comment puis-je obtenir une liste de travailleurs triée par firstName en accédant à departmet.workers? Existe-t-il un moyen d'ajouter des descripteurs de tri dans une relation to-many?Tri à de nombreuses relations Définir dans les données de base

+1

Son un vieux fil .. Mais cela a fonctionné et m'a aidé beaucoup de temps! Signet ce fil Merci à tous .. !! – Shailesh

Répondre

7

De nombreuses relations dans les données de base sont modélisées comme des ensembles non ordonnés. Toutefois, vous pouvez créer une propriété récupérée sur l'entité Department qui inclut un descripteur de tri ou vous pouvez trier définir en mémoire dans votre application (NSArrayController le fera pour vous en définissant sa propriété sortDescriptors).

+2

Je voterais pour une propriété récupérée car elle semble être la "manière la plus naturelle" dans les données de base. –

+1

@BarryWark Je suis d'accord avec Karsten, mais je pense que ce serait mieux si vous incluiez quelques détails sur la façon de créer le descripteur.Après un peu de recherche google je n'ai toujours pas trouvé comment faire un descripteur de "tri" dans une propriété récupérée, seulement comment faire correspondre les requêtes de type. – csga5000

+0

Veuillez fournir l'exemple – MobileMon

2

Vous devez définir votre propre méthode, par exemple triedWorkers. Quelque chose comme ceci:

- (NSArray *)sortedWorkers { 
    NSSortDescriptor *sortNameDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"firstName" ascending:YES] autorelease]; 
    NSArray *sortDescriptors = [[[NSArray alloc] initWithObjects:sortNameDescriptor, nil] autorelease]; 

    return [self.workers sortedArrayUsingDescriptors:sortDescriptors]; 
} 
3

le snip de code de Hunter a presque fonctionné pour moi, sauf puisque « travailleurs » est un NSSet, je devais le charger dans un NSMutableArray premier:

- (NSArray *)sortedWorkers { 
    NSSortDescriptor *sortNameDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"firstName" ascending:YES] autorelease]; 
    NSArray *sortDescriptors = [[[NSArray alloc] initWithObjects:sortNameDescriptor, nil] autorelease]; 

    NSMutableArray *sortThese = [NSMutableArray arrayWithCapacity:[self.workers count]]; 
    for (id worker in self.workers) { 
     [sortThese addObject:worker]; 
    } 

    return [sortThese sortedArrayUsingDescriptors:sortDescriptors]; 
} 
31

Amélioration mineure sur Adrian Hosey de Code:

Au lieu de itérer manuellement sur tous les travailleurs, vous pouvez aussi faire simplement:

-(NSArray *)sortedWorkers { 
    NSSortDescriptor *sortNameDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"firstName" ascending:YES] autorelease]; 
    NSArray *sortDescriptors = [[[NSArray alloc] initWithObjects:sortNameDescriptor, nil] autorelease]; 

    return [self.workers sortedArrayUsingDescriptors:sortDescriptors]; 
} 

Fait probablement exactement la même chose que votre itération interne, mais peut-être qu'ils l'ont rendu plus efficace en quelque sorte. Il est certainement moins typé ...

Note: ce qui précède ne fonctionne que sur iOS 4.0+ et OSX 10.6+. Dans les anciennes versions, vous devez remplacer la dernière ligne avec:

return [[self.workers allObjects] sortedArrayUsingDescriptors:sortDescriptors]; 
+3

Uhm, le tri est O (n * log (n)), l'itération est O (n). Bien que ce soit moins de code, il est certainement plus lent. –

+1

Bien que vrai, la différence entre les extraits de code n'est pas que l'un itére et un tri. Ils utilisent tous deux la méthode de tri, c'est juste que Adrian utilise la méthode [allObjects] pour convertir un tableau plutôt que de le créer manuellement en itérant sur l'ensemble –

+4

A partir de OS X 10.6 ni itération manuelle, ni '[allObjects] 'sont nécessaires car NSSet implémente lui-même' sortedArrayUsingDescriptors: ', en épargnant la création superflue d'un NSArray temporaire. – Regexident

1

Je remarque que cela est assez vieux, mais les gens vont toujours venir à travers elle (je l'ai fait)

poste Adrian Schönig était bon. Je l'ai trouvé utile pour les bases, mais vous devez le faire chaque fois que vous voulez accéder à l'ensemble des travailleurs. C'est très inefficace! À la place, ce qui est préférable est de faire le tri chaque fois que vous insérez un nouvel objet, puis enregistrez-le en tant que Set in CoreData. Cela signifie que chaque fois que vous appelez le CoreData, les travailleurs seront commandés.

Je l'ai fait pour mon système en utilisant une catégorie pour NSManagedObject (Worker + Methods.h). Ici j'ai la méthode d'initialisation d'un nouveau travailleur

// Worker+Methods.m 
+(Worker *)newWorkerWithFirstname:(NSString *)firstName department:(Department *)department managedContext:(NSManagedObjectContext *)context { 
    Worker *w = [NSEntityDescription insertNewObjectForEntityForName:@"Worker" inManagedObjectContext:context]; 
    w.firstName = firstName; 
    w.department = department; 

    [department orderWorkers]; 
    return s; 
} 


//Department+Methods.m 
-(void)orderServices { 
    NSSortDescriptor *sortNameDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"firstName" ascending:YES] autorelease]; 
    self.workers = [[NSSet alloc] initWithArray:[self.workers sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortNameDescriptor]]]; 
} 

c'est évidemment inefficace lorsque vous ajoutez un bon nombre de travailleurs, mais vous pouvez simplement déplacer [orderWorkers département]; se produire après que tous les travailleurs ont été ajoutés.

7

Amélioration mineure sur la solution de Adrian Schönig:

Maintenant, il est nécessaire de jeter self.workers à NSSet *

-(NSArray *)sortedWorkers { 
    NSSortDescriptor *sortNameDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"firstName" ascending:YES] autorelease]; 
    NSArray *sortDescriptors = [[[NSArray alloc] initWithObjects:sortNameDescriptor, nil] autorelease]; 

    return [(NSSet*)self.workers sortedArrayUsingDescriptors:sortDescriptors]; 
} 
Questions connexes