primaryKeyAttribute no funciona Restkit / Core Data

Acabo de instalar el framework restkit 0.9.3 y seguí el ejemplo del tablero de discusión. Bueno, todo funcionó muy bien, sin embargo, cuando intenté usar Core Data, mi class NSManagedObject de Usuario se está duplicando incluso después de declarar su primaryKeyAttribute (ID de usuario). Por ejemplo, cuando envío una request de inicio de session a mi server web, devuelvo {"user":{"id":1, "username":"teste", ...}} .. pero parece crear un nueva fila cada vez que invoca objectLoader: didLoadObjects.

Tabla de usuario:

introduzca la descripción de la imagen aquí

Código de ejemplo:

~ AppDelegate.m didFinishLaunching

 RKManagedObjectMapping* userMapping = [RKManagedObjectMapping mappingForClass:[User class]]; userMapping.primaryKeyAttribute = @"userID"; userMapping.setDefaultValueForMissingAttributes = YES; // clear out any missing attributes (token on logout) [userMapping mapKeyPathsToAttributes: @"id", @"userID", @"email", @"email", @"username", @"username", @"password", @"password", nil]; [objectManager.mappingProvider registerMapping:userMapping withRootKeyPath:@"user"]; 

~ User.m loginWithDelegate

 - (void)loginWithDelegate:(NSObject<UserAuthenticationDelegate>*)delegate { _delegate = delegate; [[RKObjectManager shanetworkingManager] postObject:self delegate:self block:^(RKObjectLoader* loader) { loader.resourcePath = @"/login"; loader.serializationMapping = [RKObjectMapping serializationMappingWithBlock:^(RKObjectMapping* mapping) { [mapping mapAttributes:@"username", @"password", nil]; }]; }]; } 

~ User.m didLoadObjects (RKObjectLoaderDelegate)

 - (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray *)objects { if ([objectLoader wasSentToResourcePath:@"/login"]) { [self loginWasSuccessful]; } NSLog(@"number of user rows: %i", [User findAll].count); } 

¿Qué estoy haciendo mal?

¿Está implementando correctamente RKManagedObjectCache? Para la debugging tuve simplemente devolver cero y me olvidé de eso. Un poco más tarde descubrí que también tenía duplicates.

El caching funciona al search objects locales y compararlos con los objects devueltos del server. Cualquier object local que no esté en la respuesta del server se eliminará. En versiones anteriores, usó una request de recuperación pero en las versiones más recientes debe realizar manualmente la request y devolver los objects reales.

Si devuelve nada, piensa que este object no está en su caching y agregará un duplicado. Intenta implementar este método:

 + (NSManagedObject *)findInstanceOfEntity:(NSEntityDescription *)entity withPrimaryKeyAttribute:(NSString *)primaryKeyAttribute value:(id)primaryKeyValue inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext 

Por ejemplo:

 + (NSManagedObject *)findInstanceOfEntity:(NSEntityDescription *)entity withPrimaryKeyAttribute:(NSString *)primaryKeyAttribute value:(id)primaryKeyValue inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext { NSFetchRequest* request = [[NSFetchRequest alloc] init]; [request setEntity: entity]; [request setFetchLimit: 1]; [request setPnetworkingicate:[NSPnetworkingicate pnetworkingicateWithFormat:@"%K = %@", primaryKeyAttribute, primaryKeyValue]]; NSArray *results = [NSManagedObject executeFetchRequest:request inContext: managedObjectContext]; if ([results count] == 0) { return nil; } return [results objectAtIndex:0]; } 

He encontrado el problema relacionado con targetObject (RKObjectLoader)

 /** * The target object to map results back onto. If nil, a new object instance * for the appropriate mapping will be created. If not nil, the results will * be used to update the targetObject's attributes and relationships. */ 

Así que cuando lo establezco en nil las llamadas postObject findOrCreateInstanceOfEntity: withPrimaryKeyAttribute: andValue

 - (void)loginWithDelegate:(NSObject<UserAuthenticationDelegate>*)delegate { _delegate = delegate; [[RKObjectManager shanetworkingManager] postObject:self delegate:self block:^(RKObjectLoader* loader) { loader.resourcePath = @"/login"; loader.targetObject = nil; loader.serializationMapping = [RKObjectMapping serializationMappingWithBlock:^(RKObjectMapping* mapping) { [mapping mapAttributes:@"username", @"password", nil]; }]; }]; } 

A partir de la última versión de RESTKit (0.23.2) puede definir la key principal como esta:

 [_mapping addAttributeMappingsFromDictionary:@{ @"id" : @"objectId", @"name" : @"name" }]; [_mapping setIdentificationAttributes:@[ @"objectId" ]]; 

Mientras objectId es su key principal en el object de datos del núcleo.