2009-06-02 14 views
32

Pobieram zestaw obiektów z magazynu trwałego danych podstawowych za pomocą żądania pobierania i predykatu. Mój obecny predykat sprawdza tylko, czy atrybut ma wartość> = pewną wartość. To wszystko działa świetnie, z tym wyjątkiem, że chcę w końcu wyłączyć wszystkie obiekty, które są obecnie przechowywane w tablicy.Dane podstawowe: Kwerenda identyfikatory obiektu w predykacie?

Zasadniczo muszę mieć możliwość wyłączenia zestawu obiektów, a jedyny sposób, w jaki mogę to zrobić, to móc uzyskać listę objectID z mojej tablicy obiektów zarządzanych i utworzyć inne wyrażenie w moim predykacie aby zapewnić, że zwrócone obiekty nie mają tego samego objectID. TO ZNACZY. @"ANY records.objectID NOT IN %@", arrayOfObjectID.

Jak mogę to zrobić?

Odpowiedz

64

Predykat jak

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

którym podmiot wniosku zwrcania jest podmiotem obiektów w tablicy, należy zrobić co chcesz. Można to oczywiście łączyć z innymi klauzulami w jednym predykacie dla żądania pobierania.

Ogólnie rzecz biorąc, porównania obiektów (np. self == %@ lub self IN %@) są porównywane pod objectID w zapytaniach dotyczących danych podstawowych. Argumentem może być instancja NSManagedObject o instancji lub z instancją NSMangedObjectID. Tak więc powyższy format predykatu może przyjąć arrayOfExcludedObjects lub [arrayOfExcludedObjects valueForKey:@"objectID"] jako argument.

+1

Tha nks za twoją pomoc. Próbowałem przy użyciu [NSPredicate predicateWithFormat: @ "self NOT IN% @", myArrayOfManagedObjects], ale wciąż otrzymuję "Nie można sparsować ciąg formatu" self NOT IN% @ "błąd w czasie wykonywania. Jakieś pomysły? –

+0

Przepraszam .. mój błąd za nie testowanie przed opublikowaniem. Poprawiłem moją odpowiedź (użyj "NOT (self IN% @)" zamiast "self NOT IN% @"). –

+0

To zadziałało dobrze dla mnie. Użyłem go do filtrowania przy użyciu złożonej logiki, która nie jest obsługiwana w SQL. Ale predicateWithBlock nie działa (z uzasadnionych przyczyn) na SQL. –

9

Podczas gdy odpowiedź @ BarryWark jest poprawna podczas pracy z żądaniami pobierania, chcę napisać ostrzeżenie dla tych, którzy spróbują zastosować tę regułę do filtrowania relacji między danymi podstawowymi a wieloma.

Krótko: Jeśli podczas filtrowania do wielu relacji użyć predykatu i swoją tablicę obiektów dla Query jest tablicą objectIDs - wtedy należy użyć self.objectID w ciągu kwerendy jak

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

Ponieważ użycie tylko (self IN %@) w przypadku filtrowania do wielu relacji spowoduje niepoprawne wyniki - to tylko NSArray, który ocenia predykaty i nie wie nic o NSManagedObjectID Core Data.

Wykonałem specjalny test kodu pokazujący to. Przepraszamy za wiele linii, ale warto. Istnieją dwie jednostki: użytkownik i post oraz użytkownik mają relację wiele do jednego o nazwie "posty".

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

wyjście 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 Roztwór

wychodził samą sytuację dlatego m umieszczając szybkiego 3 roztworu poniżej

let predicate = NSPredicate(format:"NOT (self IN %@)",[arrayofNSManagedObjects]) 
Powiązane problemy