Datos principales: ¿Objetos de consulta en un predicado?


Estoy obteniendo un conjunto de objetos de un almacén persistente Core Data usando una solicitud fetch y un predicado. Mi predicado actual simplemente comprueba si un atributo es > = un cierto valor. Todo esto funciona muy bien, excepto que finalmente quiero excluir cualquier objeto que se encuentre actualmente en una matriz.

Básicamente necesito ser capaz de excluir un conjunto de objetos, y la única manera que creo que puedo hacer esto es ser capaz de obtener una lista de objectID de mi matriz de objetos administrados, y crear otro expresión en mi predicado para asegurar que cualquier objeto devuelto no tenga el mismo objectID. I. E. @"ANY records.objectID NOT IN %@", arrayOfObjectID.

¿Cómo puedo hacer esto?

Author: rptwsthi, 2009-06-02

3 answers

Un predicado como

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

Donde la entidad de la solicitud fetch es la entidad de los objetos en la matriz, debería hacer lo que quiera. Esto puede, por supuesto, combinarse con otras cláusulas en un solo predicado para una solicitud fetch.

En general, las comparaciones de objetos (por ejemplo, self == %@ o self IN %@) se comparan con objectID en consultas de datos básicos. El argumento puede ser una instancia de NSManagedObject o una instancia de NSMangedObjectID. Así que el formato de predicado anterior podría tomar arrayOfExcludedObjects o [arrayOfExcludedObjects valueForKey:@"objectID"] como el argumento.

 67
Author: Barry Wark,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-04 18:20:13

Si bien la respuesta de @BarryWark es correcta cuando se trabaja con solicitudes de recuperación, quiero escribir una advertencia a la gente que intentará aplicar esta regla a un filtrado de Datos Principales a muchas relaciones.

En breve: Si al filtrar a-muchas relaciones usa un predicado y su matriz de objetos para IN query es una matriz de OBJETOS, entonces debe usar self.ObjectId en la cadena de consulta como

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

Porque usar solo (self IN %@) en el caso de filtrar a-muchos las relaciones resultarán en resultados incorrectos - es solo un NSArray que evalúa predicados y no sabe nada sobre las cosas NSManagedObjectID de Core Data.

He creado un código de prueba especial que muestra esto. Perdón por tantas líneas, pero valen la pena. Hay dos entidades: User y Post y User tiene una relación a-muchos llamada "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);

Salida 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})")
 9
Author: Stanislav Pankevich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-03 19:34:39

Solución Swift 3

Me enfrenté a la misma situación, por lo tanto, estoy publicando una solución swift 3 a continuación

let predicate = NSPredicate(format:"NOT (self IN %@)",[arrayofNSManagedObjects])
 1
Author: Rajat Jain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-26 10:20:26