2009-06-02 4 views
32

Ich hole eine Reihe von Objekten aus einem persistenten Core-Data-Store mit einer Abrufanforderung und einem Prädikat. Mein aktuelles Prädikat prüft einfach, ob ein Attribut> = ein bestimmter Wert ist. Das alles funktioniert großartig, außer dass ich schließlich alle Objekte ausschließen möchte, die sich momentan in einem Array befinden.Kerndaten: Abfrage ObjektIDs in einem Prädikat?

Ich muss im Grunde in der Lage sein, eine Reihe von Objekten auszuschließen, und die einzige Möglichkeit, dass ich dies tun kann, ist eine Liste von objectID von meinem verwalteten Objekte-Array zu erhalten, und erstellen Sie einen anderen Ausdruck in meinem Prädikat um sicherzustellen, dass alle zurückgegebenen Objekte nicht die gleichen objectID haben. I.E. @"ANY records.objectID NOT IN %@", arrayOfObjectID.

Wie kann ich das tun?

Antwort

64

Ein Prädikat wie

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

, wo die Einheit des Antrags sollte die Einheit der Objekte im Array holen, tun, was Sie wollen. Dies kann natürlich mit anderen Klauseln in einem einzelnen Prädikat für eine Abrufanforderung kombiniert werden.

Im Allgemeinen vergleichen Objektvergleiche (z. B. self == %@ oder self IN %@) auf objectID in Core Data-Abfragen. Das Argument kann entweder eine NSManagedObject-Instanz oder eine NSMangedObjectID Instanz sein. Das obige Prädikatformat könnte also arrayOfExcludedObjects oder [arrayOfExcludedObjects valueForKey:@"objectID"] als Argument annehmen.

+1

Tha Danke für deine Hilfe. Ich versuchte mit [NSPredicate Prädikat WithFormat: @ "Self NOT IN% @", myArrayOfManagedObjects], aber ich bekam immer eine 'Nicht in der Lage, die Formatzeichenfolge "Self NOT IN% @" Fehler zur Laufzeit zu analysieren. Irgendwelche Ideen? –

+0

Sorry .. mein Fehler für nicht testen, bevor ich gepostet habe. Ich habe meine Antwort korrigiert (benutze "NOT (self IN% @)" anstelle von "self NOT IN% @"). –

+0

Das hat gut für mich funktioniert. Ich habe es verwendet, um komplexe Logik zu filtern, die in SQL nicht unterstützt wird. Aber predicateWithBlock funktioniert (aus vernünftigen Gründen) nicht mit SQL. –

9

Während @ BarryWarks Antwort richtig ist, wenn ich mit Fetch-Anfragen arbeite, möchte ich eine Warnung an die Leute schreiben, die versuchen werden, diese Regel auf eine Filterung von Core Data to-Many Beziehungen anzuwenden.

Kurz: Wenn beim Filtern zu-viele Beziehungen, die Sie ein Prädikat und das Array von Objekten für die IN-Abfrage verwenden, ist ein Array von ObjectIDs - dann sollten Sie self.objectID in der Abfrage-String wie

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

Da nur (self IN %@) im Falle der Filterung To-viele Beziehungen zu falschen Ergebnissen führt - es ist nur ein NSArray, das Prädikate ausgewertet und es nichts über NShandagedObjectID Zeug Core Data kennt.

Ich habe einen speziellen Testcode erstellt, der dies zeigt. Sorry für so viele Zeilen, aber sie sind es wert. Es gibt zwei Entitäten: Benutzer und Post und Benutzer hat eine Zwei-zu-viele-Beziehung namens "Posts".

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); 

TLDR Ausgang

<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 -Lösung

ich die gleiche Situation konfrontiert deshalb bin ich Entsendung eine schnelle 3 Lösung unter

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