2009-07-17 1 views
13

Desidero recuperare gli oggetti B che ha una relazione a molti con l'oggetto A (ad esempio A - >> B). Ho già A in memoria. So che potrei ottenere un NSSet degli oggetti B da A, ma sarebbe meglio fare una richiesta di recupero degli oggetti B (specialmente se voglio ordinare le sezioni per data in un UITableView)?Dati principali Recupero di oggetti che sono in relazione con un altro oggetto

Come farei una tale richiesta che ottiene solo gli oggetti B appartenenti a un singolo oggetto A?

risposta

5

È necessario specificare una relazione inversa in Classe B per fare ciò che si sta chiedendo.

Tuttavia, non sono sicuro del motivo per cui si oppongono (non è previsto il gioco di parole) per afferrare il set di oggetti B già nell'oggetto A. Anche se gli oggetti stessi sono pigri, poiché si ha già A in memoria, io avere la sensazione (anche se un esperto dovrebbe verificare) che sarebbe più efficiente semplicemente prendere il set da A piuttosto che specificare un nuovo NSPredicate e creare un Fetch completamente nuovo.

Ovviamente, con "più efficiente" stiamo parlando di millisecondi, anche su un dispositivo lento come l'iPhone. Prenderò il set dall'oggetto A perché la sintassi è più pulita. Il fatto che possa essere anche più veloce è un bonus.

+1

Vorrei fare questa domanda perché voglio che gli oggetti B siano ordinati per data. E penso che potrebbe essere più veloce e meno intensivo della CPU che il database dei dati di base possa presortare un grande set (potenzialmente più di 200) di oggetti invece di usare il codice. –

+0

Devin: se si desidera ordinare gli oggetti B, è necessario aggiungerli alla domanda originale. Mi piacerebbe sapere anche la risposta! –

+0

Anche io sono interessato a questo: http://stackoverflow.com/questions/4003659/is-it-possibile-per-have-core-data-sort-il-mano-parte-di-una-molti -relationship-d. So che puoi forzare un errore. Mi chiedo se puoi ordinarlo quando lo fai? – JoBu1324

6

Se si sta già tenendo un'istanza di A, è sufficiente accedere alle istanze B correlate tramite l'accesso di A.

Se è necessario recuperare direttamente tutte le B relative a un particolare A (non in questo caso), si dovrebbe creare una richiesta di recupero per l'entità B, con un predicato basato sulla relazione (inversa) da Bs a A. (La sintassi specifica dipenderà dal nome della relazione inversa e se tale inverso è uno a uno o molti.)

2

Sono in una situazione simile.

Desidero utilizzare un NSFetchedResultsController per gestire B nella relazione da uno a molti (A - >> B). Ora, in un modo di fare questo è quello di costruire un predicato come quella qui sotto e applicarlo a un'entità B:

NSPredicate *Predicate = [NSPredicate predicateWithFormat: 
            @"ANY hasParent.label == 'A'"]; 

Ma questo è un modo terribilmente lento di fare le cose e deve essere evitato a tutti i costi. Ho provato questo su 25.000 oggetti per recuperare circa 300 e il simulatore ha impiegato circa 15 secondi. Non avrebbe finito il recupero su iPhone e si è bloccato più volte.

L'altro modo sarebbe quello di fare ciò che è già stato menzionato, creare un NSArray dal set tenuto da A e ordinarlo. Se si invia allObjects a un set si ottiene un array indietro. A è un NSManagedObject scaricato prima.

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] 
            initWithKey:@"Name" 
            ascending:YES]; 

NSArray *lotsOfB = [[[A hasRelationsTo] 
        allObjects] 
        sortedArrayUsingDescriptors: sortDescriptors]; 

Questo è molto veloce. Nessun ritardo nel simulatore o sul dispositivo. Ma non è possibile utilizzare un NSFetchedResultsController tempi tristi :-(

Speranza che aiuta.

0

Sono anche in una situazione simile.

Non ho avuto il maggior numero di oggetti come pingbat fa, ma ci sono voluti 15 sec da scaricare con "ANY hasParent.label == 'A'"

Ho bisogno di utilizzare NSFetchedREsultsController, quindi devo ri-architettura del modello.Quello che ho fatto è stato per memorizzare la relazione to-many come una proprietà stringa e costruire il predicato "hasParent contiene% @".

La lezione che ho imparato è che avere un predicato che trasversale A relazione a molti ha un calo di prestazioni BIG ..

5

È necessario utilizzare predicato con objectID del A, in questo modo:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 

NSEntityDescription *BEntity = [NSEntityDescription entityForName:@"B" inManagedObjectContext:moc]; 
[fetchRequest setEntity:BEntity]; 

NSPredicate *predicate = [NSPredicate 
predicateWithFormat:@"(relationship_to_a = %@)", [yourAInstance objectID]]; 

[fetchRequest setPredicate:predicate]; 

dove relationship_to_a è il nome della relazione con A nell'oggetto gestito B.

Spero che questo aiuti.

Btw .: Per tutte quelle altre risposte che suggerisce di utilizzare gli errori dal set rapporto: ho provato io stesso, ed è stato modo più lento di andarli a prendere, perché a quanto pare Core Data fuoco l'uno dopo l'altro i difetti (non in batch), quindi rendendolo dolorosamente lento per set più grandi.

In realtà, se si ottiene l'Un'istanza per il recupero, allora si può provare a impostare relationshipKeyPathsForPrefetching nel vostro NSFetchRequest su YES, e poi tutti gli oggetti nel rapporto non dovrebbe essere difetti. Ma questo non ha funzionato per me, quindi mi sono bloccato con la 'soluzione di recupero'.