2009-08-19 13 views
26

Ho due modelli Reparto e Lavoratore. I dipartimenti devono avere molti rapporti (lavoratori) con i lavoratori. Il lavoratore ha il campo firstName. Come posso ottenere una lista dei lavoratori ordinata per firstName accedendo a departmet.workers? C'è un modo per aggiungere i descrittori di ordinamento nella relazione to-many?Ordinamento su molti rapporti Imposta nei dati di base

+1

Il suo vecchio filo .. Ma ha funzionato e mi ha aiutato alla grande! Libro-marcatura questa discussione Grazie a tutti .. !! – Shailesh

risposta

7

Le relazioni di molti in Core Data sono modellate come insiemi non ordinati. Tuttavia, è possibile creare una proprietà recuperata nell'entità Reparto che include un descrittore di ordinamento o è possibile ordinare il set in memoria all'interno dell'applicazione (NSArrayController lo farà automaticamente impostando la proprietà sortDescriptors).

+2

Voterò per una proprietà recuperata poiché sembra il "modo più naturale" in Core Data. –

+1

@BarryWark Sono d'accordo con Karsten, ma penso che sarebbe meglio includere alcuni dettagli su come creare il descrittore.Dopo un po 'di ricerca su google non ho ancora trovato come fare un descrittore "sort" in una proprietà recuperata, solo come abbinare le query tipo. – csga5000

+0

Fornire l'esempio – MobileMon

2

È necessario definire il proprio metodo, ad esempio Lavoratori ordinati. Qualcosa di simile a questo:

- (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

codice snip di Hunter quasi funzionato per me, se non in quanto "lavoratori" è un NSSet, ho dovuto caricarlo in un NSMutableArray prima:

- (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

miglioramento Minore su Adrian Hosey di codice:

Invece di iterare manualmente su tutti i lavoratori si può anche solo fare:

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

    return [self.workers sortedArrayUsingDescriptors:sortDescriptors]; 
} 

Probabilmente fa esattamente la stessa cosa della tua iterazione internamente, ma forse lo hanno reso più efficiente in qualche modo. È sicuramente meno digitante ...

Nota: quanto sopra funziona solo su iOS 4.0+ e OSX 10.6+. Nelle versioni più vecchie è necessario sostituire l'ultima riga con:

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

Uhm, l'ordinamento è O (n * log (n)), l'iterazione è O (n). Mentre questo è meno codice, è certamente più lento. –

+1

Mentre vero, la differenza tra i frammenti di codice non è quella che itera e un tipo. Entrambi usano il metodo sort, è solo che Adrian sta usando il metodo [allObjects] per convertire in un array invece di crearne uno manualmente iterando sul set –

+4

A partire da OS X 10.6 né l'iterazione manuale, né '[allObjects] 'sono necessari poiché NSSet stesso implementa' sortedArrayUsingDescriptors: ', risparmiando la creazione superflua di un NSArray temporaneo. – Regexident

1

mi accorgo che questo è abbastanza vecchio, ma la gente sarà ancora venire attraverso di esso (ho fatto) il post di

Adrian Schönig era buono. L'ho trovato utile per le basi, ma devi fare questo genere ogni volta che vuoi accedere al Set di lavoratori. Questo è molto inefficiente!

Invece è meglio fare il tipo ogni volta che si inserisce un nuovo oggetto e quindi lo si salva come Set in CoreData. Ciò significa che ogni volta che chiami CoreData verranno ordinati i lavoratori.

Ho fatto questo per il mio sistema utilizzando una categoria per NSManagedObject (Worker + Methods.h). Qui ho il metodo init per un nuovo lavoratore

// 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]]]; 
} 

Ovviamente questo è inefficiente quando si aggiunge un sacco di lavoratori, ma si può solo spostare [Dipartimento orderWorkers]; succedere dopo che tutti gli operai sono stati aggiunti.

7

miglioramento Minore sopra soluzione di Adrian Schönig:

Ormai è necessario lanciare self.workers a 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]; 
} 
Problemi correlati