primaryKeyAttribute不工作Restkit / Core Data

我刚刚安装了框架restkit 0.9.3,并按照讨论板的例子。 那么,一切工作都很好,但是当我尝试使用核心数据时,即使在声明他的primaryKeyAttribute(userID)之后,我的用户NSManagedObject类也是重复的。 例如,当我发送一个login请求到我的networking服务器,我返回{"user":{"id":1, "username":"teste", ...}} ..但它似乎创build一个每次新行都会调用objectLoader:didLoadObjects。

用户表:

在这里输入图像说明

示例代码:

〜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 sharedManager] 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); } 

我究竟做错了什么?

你正确地实现RKManagedObjectCache? 为了debugging,我只是简单地返回零,忘记了这一点。 过了一会儿,我发现我也有重复。

caching通过获取本地对象并与服务器返回的对象进行比较来工作。 任何不在服务器响应中的本地对象都将被删除。 在较早的版本中,它使用了一个获取请求,但在较新的版本中,您必须手动执行请求并返回实际的对象。

如果你返回零,它认为这个对象不在你的caching中,并会添加一个副本。 尝试实施这个方法:

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

例如:

 + (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 setPredicate:[NSPredicate predicateWithFormat:@"%K = %@", primaryKeyAttribute, primaryKeyValue]]; NSArray *results = [NSManagedObject executeFetchRequest:request inContext: managedObjectContext]; if ([results count] == 0) { return nil; } return [results objectAtIndex:0]; } 

我发现与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. */ 

所以当我把它设置为nil postObject调用findOrCreateInstanceOfEntity:withPrimaryKeyAttribute:andValue

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

从最新的RESTKit版本(0.23.2)开始,您可以像这样定义主键:

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

而objectId是核心数据对象的主键。