2009-06-02 16 views
32

Sto recuperando un insieme di oggetti da un archivio persistente di Core Data utilizzando una richiesta di recupero e un predicato. Il mio attuale predicato controlla semplicemente se un attributo è> = un certo valore. Tutto funziona alla grande, tranne per il fatto che voglio escludere definitivamente qualsiasi oggetto che attualmente è contenuto in un array.Dati principali: query objectID in un predicato?

Fondamentalmente ho bisogno di essere in grado di escludere un insieme di oggetti, e l'unico modo in cui penso di poterlo fare è essere in grado di ottenere un elenco di objectID dalla mia matrice di oggetti gestiti e creare un'altra espressione nel mio predicato per garantire che tutti gli oggetti restituiti non abbiano lo stesso objectID. OSSIA @"ANY records.objectID NOT IN %@", arrayOfObjectID.

Come posso fare questo?

risposta

64

Un predicato come

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT (self IN %@)", arrayOfExcludedObjects]; 

in cui l'entità della richiesta di recupero è l'entità degli oggetti nella matrice, dovrebbe fare quello che vuoi. Questo può, naturalmente, essere combinato con altre clausole in un singolo predicato per una richiesta di recupero.

In generale, i confronti tra oggetti (ad esempio self == %@ o self IN %@) confrontano su objectID nelle query di dati di base. L'argomento può essere un'istanza NSManagedObject o un'istanza NSMangedObjectID. Quindi il formato di predicato sopra potrebbe richiedere arrayOfExcludedObjects o [arrayOfExcludedObjects valueForKey:@"objectID"] come argomento.

+1

Tha nks per il tuo aiuto. Ho provato a utilizzare [NSPredicate predicateWithFormat: @ "self NOT IN% @", myArrayOfManagedObjects] ma ho ricevuto un errore "Impossibile analizzare la stringa di formato" auto NOT IN% @ "in fase di esecuzione. Qualche idea? –

+0

Scusate .. il mio errore per non testare prima ho postato. Ho corretto la mia risposta (usa "NOT (self IN% @)" invece di "self NOT IN% @"). –

+0

Questo ha funzionato bene per me. L'ho usato per filtrare usando una logica complessa che non è supportata in SQL. Ma predicateWithBlock non funziona (per ragioni ragionevoli) su SQL. –

9

Mentre la risposta di @ BarryWark è corretta quando si lavora con le richieste di recupero, voglio scrivere un avvertimento agli utenti che cercheranno di applicare questa regola a un filtro di Core Data a molte relazioni.

Poco: se durante il filtraggio a-molti si utilizza un predicato e l'array di oggetti per la query IN è un array di objectIds - allora dovreste usare self.objectID nella stringa di query come

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(self.objectID IN %@)", arrayOfObjectIDs]; 

Poiché l'utilizzo di solo (self IN %@) in caso di filtraggio su più relazioni genererà risultati non corretti: è solo un NSArray che valuta i predicati e non conosce nulla sull'oggetto NSManagedObjectID di Core Data.

Ho creato un codice di prova speciale che mostra questo. Ci scusiamo per così tante battute, ma ne vale la pena. Esistono due entità: Utente e Posta e Utente hanno una relazione a molti denominata "post".

User *user = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([User class]) inManagedObjectContext:managedObjectContext()]; 

Post *post = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([Post class]) inManagedObjectContext:managedObjectContext()]; 

[user addPostsObject:post]; 

[managedObjectContext() save:nil]; 

// 1. Both filtered relationship array and fetch result are correct! 
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(self IN %@)", @[ post ]]; 

NSSet *filteredRelationship = [user.posts filteredSetUsingPredicate:predicate]; 

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Post"]; 
NSArray *fetchResult = [managedObjectContext() executeFetchRequest:fetchRequest error:nil]; 

NSLog(@"\n\n\nPredicate: %@", predicate); 
NSLog(@"filteredRelationship: %@", filteredRelationship); 
NSLog(@"fetchResult: %@", fetchResult); 

// 2. Filtered relationship array is empty (wrong), fetch result is correct, ! 
predicate = [NSPredicate predicateWithFormat:@"(self IN %@)", @[ post.objectID ]]; 

filteredRelationship = [user.posts filteredSetUsingPredicate:predicate]; 

fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Post"]; 
fetchResult = [managedObjectContext() executeFetchRequest:fetchRequest error:nil]; 

NSLog(@"\n\n\nPredicate: %@", predicate); 
NSLog(@"filteredRelationship: %@", filteredRelationship); 
NSLog(@"fetchResult: %@", fetchResult); 

// 3. Filtered relationship array is empty (wrong), fetch result is correct 
predicate = [NSPredicate predicateWithFormat:@"(self.objectID IN %@)", @[ post ]]; 

filteredRelationship = [user.posts filteredSetUsingPredicate:predicate]; 

fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Post"]; 
fetchResult = [managedObjectContext() executeFetchRequest:fetchRequest error:nil]; 

NSLog(@"\n\n\nPredicate: %@", predicate); 
NSLog(@"filteredRelationship: %@", filteredRelationship); 
NSLog(@"fetchResult: %@", fetchResult); 

// 4. Filtered relationship array is correct, fetch result is correct 
predicate = [NSPredicate predicateWithFormat:@"(self.objectID IN %@)", @[ post.objectID ]]; 

filteredRelationship = [user.posts filteredSetUsingPredicate:predicate]; 

fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Post"]; 
fetchResult = [managedObjectContext() executeFetchRequest:fetchRequest error:nil]; 

NSLog(@"\n\n\nPredicate: %@", predicate); 
NSLog(@"filteredRelationship: %@", filteredRelationship); 
NSLog(@"fetchResult: %@", fetchResult); 

uscita TLDR

<redacted> Predicate: SELF IN {<Post: 0x2a04f10> (entity: Post; id: 0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1> ; data: { content = nil; title = nil; user = "0x2af2a20 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/User/p1>"; })} 

<redacted> filteredRelationship: {(<Post: 0x2a04f10> (entity: Post; id: 0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1> ; data: { content = nil; title = nil; user = "0x2af2a20 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/User/p1>"; }))} 

<redacted> fetchResult: ("<Post: 0x2a04f10> (entity: Post; id: 0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1> ; data: {\n content = nil;\n title = nil;\n user = \"0x2af2a20 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/User/p1>\";\n})") 

<redacted> Predicate: SELF IN {0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1>} 

<redacted> filteredRelationship: {()} 

<redacted> fetchResult: ("<Post: 0x2a04f10> (entity: Post; id: 0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1> ; data: {\n content = nil;\n title = nil;\n user = \"0x2af2a20 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/User/p1>\";\n})") 

<redacted> Predicate: objectID IN {<Post: 0x2a04f10> (entity: Post; id: 0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1> ; data: { content = nil; title = nil; user = "0x2af2a20 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/User/p1>";})} 

<redacted> filteredRelationship: {()} 

<redacted> fetchResult: ("<Post: 0x2a04f10> (entity: Post; id: 0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1> ; data: {\n content = nil;\n title = nil;\n user = \"0x2af2a20 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/User/p1>\";\n})") 

<redacted> Predicate: objectID IN {0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1>} 

<redacted> filteredRelationship: {(<Post: 0x2a04f10> (entity: Post; id: 0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1> ; data: { content = nil; title = nil; user = "0x2af2a20 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/User/p1>";}))} 

<redacted> fetchResult: ("<Post: 0x2a04f10> (entity: Post; id: 0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1> ; data: {\n content = nil;\n title = nil;\n user = \"0x2af2a20 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/User/p1>\";\n})") 
0

Swift 3 soluzione

Ho affrontato la stessa situazione pertanto I m pubblicare un 3 soluzione rapida sotto

let predicate = NSPredicate(format:"NOT (self IN %@)",[arrayofNSManagedObjects]) 
Problemi correlati