Core Data: Abfrage ObjectIDs in einem Prädikat?
Frage
Ich bin eine Reihe von Objekten aus einem Core Data persistenten Speicher zu holen eine Anfrage und ein Prädikat holen verwenden. Mein aktuelles Prädikat prüft lediglich, ob ein Attribut> = ein bestimmte Wert. Das alles funktioniert gut, außer, dass ich will, um endlich alle Objekte auszuschließen, die zur Zeit in einer Reihe gehalten werden.
Ich muss grundsätzlich in der Lage eine Reihe von Objekten auszuschließen, und der einzige Weg, ich glaube, ich kann dies tun zu können, ist eine Liste von objectID
von meinem verwalteten Objekte Array bekommen, und erstellen Sie einen anderen Ausdruck in meinem Prädikat sicherzustellen, dass alle zurückgegebenen Objekte nicht den gleichen objectID
haben. I.E.@"ANY records.objectID NOT IN %@", arrayOfObjectID
.
Wie kann ich das tun?
Lösung
Ein Prädikat wie
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT (self IN %@)", arrayOfExcludedObjects];
, wo die Einheit der Abrufanforderung ist die Einheit der Objekte in dem Array, sollte das tun, was Sie wollen. Dies kann natürlich mit anderen Klauseln in einem einzigen Prädikat für eine Abrufanforderung kombiniert werden.
Im allgemeinen Objektvergleich (z self == %@
oder self IN %@
) miteinander vergleichen objectID
in Core Data Abfragen. Das Argument kann entweder eine NSManagedObject Instanz oder eine NSMangedObjectID
Instanz. Also das Prädikat Format oben könnte arrayOfExcludedObjects
oder [arrayOfExcludedObjects valueForKey:@"objectID"]
als Argument nehmen.
Andere Tipps
Während @ BarryWark die Antwort richtig ist, wenn sie mit Abrufanforderungen arbeiten, habe ich eine Warnung an die Leute schreiben wollen, die versuchen, diese Regel zu einer Filterung von Core Data zu-viele 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 ein Array von ObjectIDs ist - dann sollten Sie verwenden self.objectID in der Abfrage-String wie
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(self.objectID IN %@)", arrayOfObjectIDs];
Da mit nur (self IN %@)
im Fall von Filtern zu-viele Beziehungen zu falschen Ergebnissen führen wird -. Es ist nur ein NSArray, die Prädikate auswertet und sie weiß nichts von Core-Data NSManagedObjectID Sachen
Ich habe spezielle Testcode zeigt diese in Handarbeit gemacht. Sorry für so viele Zeilen, aber sie lohnt sich. Es gibt zwei Einheiten:. User und Post und Benutzer eine n-Beziehung „Beiträge“ genannt haben
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})")
Swift 3 Lösung
stand ich die gleiche Situation deshalb bin ich eine schnelle 3 Lösung unter
Buchunglet predicate = NSPredicate(format:"NOT (self IN %@)",[arrayofNSManagedObjects])