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})")
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? –
Scusate .. il mio errore per non testare prima ho postato. Ho corretto la mia risposta (usa "NOT (self IN% @)" invece di "self NOT IN% @"). –
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. –