2012-10-05 12 views
6

Setup: ho una collezione di oggetti padre, li chiamo ObjectA. Ogni ObjectA ha una relazione uno a molti con l'oggetto B. Quindi, un ObjectA può contenere 0..n ObjectB-s, e ogni ObjectB ha un ObjectA specifico come genitore.Come ordinare i risultati dei dati di base in base a un attributo della raccolta di oggetti correlati?

Ora, vorrei eseguire un recupero dei dati di base di ObjectA-s, in cui sono ordinati in base al loro ultimo ObjectB. È possibile creare un descrittore di ordinamento per questo?

C'è a related question che descrive esattamente la stessa situazione. La risposta suggerisce denormalizzare l'attributo da ObjectB in ObjectA. Questo sarebbe OK se non c'è davvero modo di farlo con una richiesta di recupero.

La domanda relativa menziona anche:

Actually, I just had an idea! Maybe I can sort Conversations by [email protected]

ho provato. Non sembra possibile. Viene visualizzato questo errore:

2012-10-05 17:51:42.813 xxx[6398:c07] *** Terminating app due to uncaught 
exception 'NSInvalidArgumentException', reason: 'Keypath containing 
KVC aggregate where there shouldn't be one; failed to handle 
[email protected]' 

È denormalizzare l'attributo in ObjectA l'unica/migliore soluzione?

risposta

0

Si potrebbe aggiungere un attributo in ObjectB che è il timestamp della data di aggiuntivo, poi nella richiesta di recupero si può fare qualcosa di simile:

NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:@"objectB.addTime" ascending:YES]; 
... 
fetchRequest.sortDescriptors = @[descriptor]; 
+2

Questo non ha funzionato per me: 'NSInvalidArgumentException', motivo: 'to-many key not allowed here' –

0

So che questa domanda è un po 'vecchio ma che cosa Ho fatto è stato ottenere tutti gli ObjectB, scorrere i risultati e tirare fuori la proprietà ObjectB e aggiungerlo a un nuovo array.

NSFetchRequest *fetchRequest = [NSFetchRequest new]; 
[fetchRequest setEntity:self.entityDescForObjectB]; 

// sort 
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:YES]; 
[fetchRequest setSortDescriptors:@[sortDescriptor]]; 

NSError *error = nil; 
NSArray *fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error]; 
if (fetchedObjects == nil) { 
    NSLog(@"Error fetching objects: %@", error.localizedDescription); 
    return; 
} 

// pull out all the ObjectA objects 
NSMutableArray *tmp = [@[] mutableCopy]; 
for (ObjectB *obj in fetchedObjects) { 
    if ([tmp containsObject:obj.objectA]) { 
     continue; 
    } 
    [tmp addObject:obj.objectA]; 
} 

Questo funziona perché CoreData è un oggetto grafico in modo da poter lavorare all'indietro. Il loop alla fine controlla in sostanza se l'array tmp ha già un'istanza ObjectA specifica e se non lo aggiunge all'array.

È importante ordinare gli ObjectB altrimenti questo esercizio è inutile.